Skip to content

Commit ae2d344

Browse files
committed
memory footprint work - avoid read-only blacklist data duplication
1 parent afedf76 commit ae2d344

4 files changed

Lines changed: 114 additions & 292 deletions

File tree

js/background.js

Lines changed: 2 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -21,182 +21,6 @@
2121

2222
/******************************************************************************/
2323

24-
// unpacked:
25-
// map[hostname] = true/false
26-
// packed
27-
// map[tld].[leftover.length] = haystack on which to perform binary search
28-
//
29-
// Idea for mapping according to length inspired from reading the section
30-
// "String-based Binary Search" @ http://ejohn.org/blog/revised-javascript-dictionary-search/
31-
// Except for the core binary search I reused my own faithful version which has
32-
// served me well over time.
33-
//
34-
// Figuratively speaking, this means when looking up a hostname, aka the needle,
35-
// the TLD of the hostname tells us on which farm we must go, and the length
36-
// of the hostname minus TLD tells us which haystack on that farm with must
37-
// look into.
38-
//
39-
// Before, with quickIndexOf(), I was binary-searching one big ass haystack,
40-
// now, using very easy to compute hostname patterns, I lookup a smaller
41-
// haystack before binary-searching. But I appreciate especially the reduced
42-
// memory footprint -- through the removal of all redundant information within
43-
// a single haystack.
44-
//
45-
// Stats:
46-
// Using Object for farm: sizeof(blacklistReadonly): 1,050,028
47-
// Using Array for farm: sizeof(blacklistReadonly): 1,050,640
48-
// So I will stick to using an Array because:
49-
// http://jsperf.com/performance-of-array-vs-object/49
50-
51-
var blacklistReadonly = {
52-
packed: {},
53-
unpacked: null,
54-
55-
unpack: function() {
56-
var unpacked = this.unpacked;
57-
if ( unpacked ) {
58-
return unpacked;
59-
}
60-
unpacked = {};
61-
this._unpack(unpacked, '');
62-
this.packed = null;
63-
this.unpacked = unpacked;
64-
return unpacked;
65-
},
66-
67-
pack: function() {
68-
var packed = this.packed;
69-
if ( packed ) {
70-
return packed;
71-
}
72-
packed = {};
73-
var unpacked = this.unpacked;
74-
var hostnames = Object.keys(unpacked);
75-
var iHostname = hostnames.length;
76-
var hostname, idot, tld, hnPrefix;
77-
var len, farm, haystack;
78-
while ( iHostname-- ) {
79-
hostname = hostnames[iHostname];
80-
idot = hostname.lastIndexOf('.');
81-
hnPrefix = hostname.slice(0, idot);
82-
tld = hostname.slice(idot+1);
83-
len = hnPrefix.length;
84-
if ( !packed[tld] ) {
85-
packed[tld] = [];
86-
}
87-
farm = packed[tld];
88-
if ( !farm[len] ) {
89-
farm[len] = {};
90-
}
91-
haystack = farm[len];
92-
haystack[hnPrefix] = true;
93-
}
94-
var tldKeys = Object.keys(packed);
95-
var iTld = tldKeys.length;
96-
while ( iTld-- ) {
97-
tld = tldKeys[iTld];
98-
farm = packed[tld];
99-
len = farm.length;
100-
while ( len-- ) {
101-
if ( farm[len] !== undefined ) {
102-
farm[len] = Object.keys(farm[len]).sort().join('');
103-
}
104-
}
105-
}
106-
this.unpacked = null;
107-
this.packed = packed;
108-
return packed;
109-
},
110-
111-
toFilters: function(des) {
112-
var unpacked = this.unpacked;
113-
if ( unpacked ) {
114-
var hostnames = Object.keys(unpacked);
115-
var i = hostnames.length;
116-
while ( i-- ) {
117-
des['*/' + hostnames[i]] = true;
118-
}
119-
return;
120-
}
121-
this._unpack(des, '*/');
122-
},
123-
124-
addOne: function(hostname) {
125-
var unpacked = this.unpacked || this.unpack();
126-
unpacked[hostname] = true;
127-
},
128-
129-
addMany: function(s) {
130-
var unpacked = this.unpacked || this.unpack();
131-
var hostnames = s.split(/\s+/);
132-
var i = hostnames.length;
133-
var hostname;
134-
while ( i-- ) {
135-
hostname = hostnames[i];
136-
if ( hostname.length ) {
137-
unpacked[hostname.toLowerCase()] = true;
138-
}
139-
}
140-
},
141-
142-
find: function(hostname) {
143-
var packed = this.packed || this.pack();
144-
var idot = hostname.lastIndexOf('.');
145-
var tld = hostname.slice(idot+1);
146-
var farm = packed[tld];
147-
if ( !farm ) {
148-
return false;
149-
}
150-
var hnPrefix = hostname.slice(0, idot);
151-
var len = hnPrefix.length;
152-
var haystack = farm[len];
153-
if ( !haystack ) {
154-
return false;
155-
}
156-
var left = 0;
157-
var right = Math.round(haystack.length / len);
158-
var i, needle;
159-
while ( left < right ) {
160-
i = left + right >> 1;
161-
needle = haystack.substr(i * len, len);
162-
if ( hnPrefix < needle ) {
163-
right = i;
164-
} else if ( hnPrefix > needle ) {
165-
left = i + 1;
166-
} else {
167-
return true;
168-
}
169-
}
170-
return false;
171-
},
172-
173-
// this exists only in order to avoid code duplication
174-
_unpack: function(des, prefix) {
175-
var packed = this.packed;
176-
var tlds = Object.keys(packed);
177-
var iTld = tlds.length;
178-
var tld, farm, len;
179-
var haystack, iStraw;
180-
while ( iTld-- ) {
181-
tld = tlds[iTld];
182-
farm = packed[tld];
183-
len = farm.length;
184-
while ( len-- ) {
185-
haystack = farm[len];
186-
if ( haystack ) {
187-
iStraw = haystack.length;
188-
while ( iStraw ) {
189-
iStraw -= len;
190-
des[prefix + haystack.substr(iStraw, len) + '.' + tld] = true;
191-
}
192-
}
193-
}
194-
}
195-
}
196-
};
197-
198-
/******************************************************************************/
199-
20024
var HTTPSB = {
20125
manifest: chrome.runtime.getManifest(),
20226

@@ -244,14 +68,14 @@ var HTTPSB = {
24468
// effective lists
24569
whitelist: { },
24670
blacklist: { '*/*': true },
247-
graylist: { }, // this will override preset blacklists
71+
graylist: { },
24872
// user lists
24973
whitelistUser: {},
25074
blacklistUser: {},
25175
graylistUser: {}, // this will override preset blacklists
25276

25377
// Current entries from remote blacklists
254-
blacklistReadonly: blacklistReadonly,
78+
blacklistReadonly: {},
25579

25680
// https://github.com/gorhill/httpswitchboard/issues/19
25781
excludeRegex: /^https?:\/\/chrome\.google\.com\/(extensions|webstore)/,

0 commit comments

Comments
 (0)