code review: reuse last decomposed hostname (hit rate = 75%)

This commit is contained in:
Raymond Hill 2018-06-03 13:27:42 -04:00
parent 46c81ea691
commit 7766786b2c
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
4 changed files with 83 additions and 107 deletions

View File

@ -70,41 +70,9 @@ var nameToActionMap = {
/******************************************************************************/ /******************************************************************************/
// For performance purpose, as simple tests as possible // For performance purpose, as simple tests as possible
var reHostnameVeryCoarse = /[g-z_-]/;
var reIPv4VeryCoarse = /\.\d+$/;
var reBadHostname = /[^0-9a-z_.\[\]:%-]/; var reBadHostname = /[^0-9a-z_.\[\]:%-]/;
var reNotASCII = /[^\x20-\x7F]/; var reNotASCII = /[^\x20-\x7F]/;
// http://tools.ietf.org/html/rfc5952
// 4.3: "MUST be represented in lowercase"
// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers
var isIPAddress = function(hostname) {
if ( reHostnameVeryCoarse.test(hostname) ) {
return false;
}
if ( reIPv4VeryCoarse.test(hostname) ) {
return true;
}
return hostname.startsWith('[');
};
var toBroaderHostname = function(hostname) {
var pos = hostname.indexOf('.');
if ( pos !== -1 ) {
return hostname.slice(pos + 1);
}
return hostname !== '*' && hostname !== '' ? '*' : '';
};
var toBroaderIPAddress = function(ipaddress) {
return ipaddress !== '*' && ipaddress !== '' ? '*' : '';
};
var selectHostnameBroadener = function(hostname) {
return isIPAddress(hostname) ? toBroaderIPAddress : toBroaderHostname;
};
/******************************************************************************/ /******************************************************************************/
Matrix.prototype.reset = function() { Matrix.prototype.reset = function() {
@ -114,6 +82,8 @@ Matrix.prototype.reset = function() {
this.z = ''; this.z = '';
this.rules = new Map(); this.rules = new Map();
this.changed = false; this.changed = false;
this.decomposedSource = [];
this.decomposedDestination = [];
}; };
/******************************************************************************/ /******************************************************************************/
@ -291,14 +261,13 @@ var domainFromHostname = µBlock.URI.domainFromHostname;
/******************************************************************************/ /******************************************************************************/
Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type, broadener) { Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) {
µBlock.decomposeHostname(srcHostname, this.decomposedSource);
this.type = type; this.type = type;
var bitOffset = typeBitOffsets[type]; let bitOffset = typeBitOffsets[type];
var s = srcHostname; for ( let shn of this.decomposedSource ) {
var v; this.z = shn;
for (;;) { let v = this.rules.get(shn + ' ' + desHostname);
this.z = s;
v = this.rules.get(s + ' ' + desHostname);
if ( v !== undefined ) { if ( v !== undefined ) {
v = v >>> bitOffset & 3; v = v >>> bitOffset & 3;
if ( v !== 0 ) { if ( v !== 0 ) {
@ -306,8 +275,6 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type, broade
return v; return v;
} }
} }
s = broadener(s);
if ( s === '' ) { break; }
} }
// srcHostname is '*' at this point // srcHostname is '*' at this point
this.r = 0; this.r = 0;
@ -318,29 +285,24 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type, broade
Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) { Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
// Pathological cases. // Pathological cases.
var d = desHostname; if ( desHostname === '' ) {
if ( d === '' ) {
this.r = 0; this.r = 0;
return 0; return 0;
} }
// Prepare broadening handlers -- depends on whether we are dealing with
// a hostname or IP address.
var broadenSource = selectHostnameBroadener(srcHostname),
broadenDestination = selectHostnameBroadener(desHostname);
// Precedence: from most specific to least specific // Precedence: from most specific to least specific
// Specific-destination, any party, any type // Specific-destination, any party, any type
while ( d !== '*' ) { µBlock.decomposeHostname(desHostname, this.decomposedDestination);
this.y = d; for ( let dhn of this.decomposedDestination ) {
if ( this.evaluateCellZ(srcHostname, d, '*', broadenSource) !== 0 ) { if ( dhn === '*' ) { break; }
this.y = dhn;
if ( this.evaluateCellZ(srcHostname, dhn, '*') !== 0 ) {
return this.r; return this.r;
} }
d = broadenDestination(d);
} }
var thirdParty = is3rdParty(srcHostname, desHostname); let thirdParty = is3rdParty(srcHostname, desHostname);
// Any destination // Any destination
this.y = '*'; this.y = '*';
@ -349,34 +311,34 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
if ( thirdParty ) { if ( thirdParty ) {
// 3rd-party, specific type // 3rd-party, specific type
if ( type === 'script' ) { if ( type === 'script' ) {
if ( this.evaluateCellZ(srcHostname, '*', '3p-script', broadenSource) !== 0 ) { if ( this.evaluateCellZ(srcHostname, '*', '3p-script') !== 0 ) {
return this.r; return this.r;
} }
} else if ( type === 'sub_frame' ) { } else if ( type === 'sub_frame' ) {
if ( this.evaluateCellZ(srcHostname, '*', '3p-frame', broadenSource) !== 0 ) { if ( this.evaluateCellZ(srcHostname, '*', '3p-frame') !== 0 ) {
return this.r; return this.r;
} }
} }
// 3rd-party, any type // 3rd-party, any type
if ( this.evaluateCellZ(srcHostname, '*', '3p', broadenSource) !== 0 ) { if ( this.evaluateCellZ(srcHostname, '*', '3p') !== 0 ) {
return this.r; return this.r;
} }
} else if ( type === 'script' ) { } else if ( type === 'script' ) {
// 1st party, specific type // 1st party, specific type
if ( this.evaluateCellZ(srcHostname, '*', '1p-script', broadenSource) !== 0 ) { if ( this.evaluateCellZ(srcHostname, '*', '1p-script') !== 0 ) {
return this.r; return this.r;
} }
} }
// Any destination, any party, specific type // Any destination, any party, specific type
if ( supportedDynamicTypes.hasOwnProperty(type) ) { if ( supportedDynamicTypes.hasOwnProperty(type) ) {
if ( this.evaluateCellZ(srcHostname, '*', type, broadenSource) !== 0 ) { if ( this.evaluateCellZ(srcHostname, '*', type) !== 0 ) {
return this.r; return this.r;
} }
} }
// Any destination, any party, any type // Any destination, any party, any type
if ( this.evaluateCellZ(srcHostname, '*', '*', broadenSource) !== 0 ) { if ( this.evaluateCellZ(srcHostname, '*', '*') !== 0 ) {
return this.r; return this.r;
} }

View File

@ -60,40 +60,12 @@ var nameToSwitchStateMap = {
/******************************************************************************/ /******************************************************************************/
// For performance purpose, as simple tests as possible // For performance purpose, as simple tests as possible
var reHostnameVeryCoarse = /[g-z_-]/;
var reIPv4VeryCoarse = /\.\d+$/;
var reNotASCII = /[^\x20-\x7F]/; var reNotASCII = /[^\x20-\x7F]/;
// http://tools.ietf.org/html/rfc5952 // http://tools.ietf.org/html/rfc5952
// 4.3: "MUST be represented in lowercase" // 4.3: "MUST be represented in lowercase"
// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers // Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers
var isIPAddress = function(hostname) {
if ( reHostnameVeryCoarse.test(hostname) ) {
return false;
}
if ( reIPv4VeryCoarse.test(hostname) ) {
return true;
}
return hostname.startsWith('[');
};
var toBroaderHostname = function(hostname) {
var pos = hostname.indexOf('.');
if ( pos !== -1 ) {
return hostname.slice(pos + 1);
}
return hostname !== '*' && hostname !== '' ? '*' : '';
};
var toBroaderIPAddress = function(ipaddress) {
return ipaddress !== '*' && ipaddress !== '' ? '*' : '';
};
var selectHostnameBroadener = function(hostname) {
return isIPAddress(hostname) ? toBroaderIPAddress : toBroaderHostname;
};
/******************************************************************************/ /******************************************************************************/
HnSwitches.prototype.reset = function() { HnSwitches.prototype.reset = function() {
@ -102,6 +74,7 @@ HnSwitches.prototype.reset = function() {
this.z = ''; this.z = '';
this.r = 0; this.r = 0;
this.changed = true; this.changed = true;
this.decomposedSource = [];
}; };
/******************************************************************************/ /******************************************************************************/
@ -220,21 +193,17 @@ HnSwitches.prototype.evaluateZ = function(switchName, hostname) {
return false; return false;
} }
this.n = switchName; this.n = switchName;
var bits, µBlock.decomposeHostname(hostname, this.decomposedSource);
hn = hostname, for ( let shn of this.decomposedSource ) {
broadenSource = selectHostnameBroadener(hn); let bits = this.switches.get(shn);
for (;;) {
bits = this.switches.get(hn);
if ( bits !== undefined ) { if ( bits !== undefined ) {
bits = bits >>> bitOffset & 3; bits = bits >>> bitOffset & 3;
if ( bits !== 0 ) { if ( bits !== 0 ) {
this.z = hn; this.z = shn;
this.r = bits; this.r = bits;
return bits === 1; return bits === 1;
} }
} }
hn = broadenSource(hn);
if ( hn === '' ) { break; }
} }
this.r = 0; this.r = 0;
return false; return false;

View File

@ -137,6 +137,7 @@ URLNetFiltering.prototype.reset = function() {
this.type = ''; this.type = '';
this.r = 0; this.r = 0;
this.changed = false; this.changed = false;
this.decomposedSource = [];
}; };
/******************************************************************************/ /******************************************************************************/
@ -207,32 +208,31 @@ URLNetFiltering.prototype.evaluateZ = function(context, target, type) {
if ( this.rules.size === 0 ) { if ( this.rules.size === 0 ) {
return 0; return 0;
} }
var entries, pos, i, entry; µBlock.decomposeHostname(context, this.decomposedSource);
for (;;) { for ( let shn of this.decomposedSource ) {
this.context = context; this.context = shn;
if ( (entries = this.rules.get(context + ' ' + type)) ) { let entries = this.rules.get(shn + ' ' + type);
i = indexOfMatch(entries, target); if ( entries !== undefined ) {
let i = indexOfMatch(entries, target);
if ( i !== -1 ) { if ( i !== -1 ) {
entry = entries[i]; let entry = entries[i];
this.url = entry.url; this.url = entry.url;
this.type = type; this.type = type;
this.r = entry.action; this.r = entry.action;
return this.r; return this.r;
} }
} }
if ( (entries = this.rules.get(context + ' *')) ) { entries = this.rules.get(shn + ' *');
i = indexOfMatch(entries, target); if ( entries !== undefined ) {
let i = indexOfMatch(entries, target);
if ( i !== -1 ) { if ( i !== -1 ) {
entry = entries[i]; let entry = entries[i];
this.url = entry.url; this.url = entry.url;
this.type = '*'; this.type = '*';
this.r = entry.action; this.r = entry.action;
return this.r; return this.r;
} }
} }
if ( context === '*' ) { break; }
pos = context.indexOf('.');
context = pos !== -1 ? context.slice(pos + 1) : '*';
} }
return 0; return 0;
}; };

View File

@ -416,3 +416,48 @@
}; };
/******************************************************************************/ /******************************************************************************/
µBlock.decomposeHostname = (function() {
// For performance purpose, as simple tests as possible
let reHostnameVeryCoarse = /[g-z_-]/;
let reIPv4VeryCoarse = /\.\d+$/;
let isIPAddress = function(hostname) {
if ( reHostnameVeryCoarse.test(hostname) ) {
return false;
}
if ( reIPv4VeryCoarse.test(hostname) ) {
return true;
}
return hostname.startsWith('[');
};
let toBroaderHostname = function(hostname) {
let pos = hostname.indexOf('.');
if ( pos !== -1 ) {
return hostname.slice(pos + 1);
}
return hostname !== '*' && hostname !== '' ? '*' : '';
};
let toBroaderIPAddress = function(ipaddress) {
return ipaddress !== '*' && ipaddress !== '' ? '*' : '';
};
return function decomposeHostname(hostname, decomposed) {
if ( decomposed.length === 0 || decomposed[0] !== hostname ) {
let broaden = isIPAddress(hostname) ?
toBroaderIPAddress :
toBroaderHostname;
decomposed[0] = hostname;
let i = 1;
for (;;) {
hostname = broaden(hostname);
if ( hostname === '' ) { break; }
decomposed[i++] = hostname;
}
decomposed.length = i;
}
return decomposed;
};
})();