further refactoring + performance: skip surveying DOM after too many empty resultset

This commit is contained in:
gorhill 2016-07-09 19:21:46 -04:00
parent ed315d0a3b
commit 02e6b088ef
6 changed files with 752 additions and 755 deletions

View File

@ -111,8 +111,12 @@ vAPI.executionCost.start();
/******************************************************************************/
vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) +
Math.random().toString(36).slice(2);
vAPI.randomToken = function() {
return String.fromCharCode(Date.now() % 26 + 97) +
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
};
vAPI.sessionId = vAPI.randomToken();
vAPI.chrome = true;
vAPI.setTimeout = vAPI.setTimeout || self.setTimeout.bind(self);

View File

@ -102,8 +102,13 @@ vAPI.executionCost.start();
/******************************************************************************/
vAPI.firefox = true;
vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) +
Math.random().toString(36).slice(2);
vAPI.randomToken = function() {
return String.fromCharCode(Date.now() % 26 + 97) +
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
};
vAPI.sessionId = vAPI.randomToken();
/******************************************************************************/

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,8 @@ var isBadRegex = function(s) {
return false;
};
var cosmeticSurveyingMissCountMax = parseInt(vAPI.localStorage.getItem('cosmeticSurveyingMissCountMax'), 10) || 10;
/******************************************************************************/
/*
var histogram = function(label, buckets) {
@ -463,6 +465,7 @@ SelectorCacheEntry.prototype.netHighWaterMark = 30;
SelectorCacheEntry.prototype.reset = function() {
this.cosmetic = {};
this.cosmeticSurveyingMissCount = 0;
this.net = {};
this.netCount = 0;
this.lastAccessTime = Date.now();
@ -481,8 +484,13 @@ SelectorCacheEntry.prototype.dispose = function() {
/******************************************************************************/
SelectorCacheEntry.prototype.addCosmetic = function(selectors) {
var dict = this.cosmetic;
var i = selectors.length || 0;
if ( i === 0 ) {
this.cosmeticSurveyingMissCount += 1;
return;
}
this.cosmeticSurveyingMissCount = 0;
var dict = this.cosmetic;
while ( i-- ) {
dict[selectors[i]] = true;
}
@ -555,6 +563,7 @@ SelectorCacheEntry.prototype.remove = function(type) {
this.lastAccessTime = Date.now();
if ( type === undefined || type === 'cosmetic' ) {
this.cosmetic = {};
this.cosmeticSurveyingMissCount = 0;
}
if ( type === undefined || type === 'net' ) {
this.net = {};
@ -652,9 +661,9 @@ var FilterContainer = function() {
this.type0NoDomainHash = 'type0NoDomain';
this.type1NoDomainHash = 'type1NoDomain';
this.parser = new FilterParser();
this.selectorCachePruneDelay = 5 * 60 * 1000; // 5 minutes
this.selectorCacheAgeMax = 20 * 60 * 1000; // 20 minutes
this.selectorCacheCountMin = 10;
this.selectorCachePruneDelay = 10 * 60 * 1000; // 15 minutes
this.selectorCacheAgeMax = 120 * 60 * 1000; // 120 minutes
this.selectorCacheCountMin = 25;
this.selectorCacheTimer = null;
this.reHasUnicode = /[^\x00-\x7F]/;
this.punycode = punycode;
@ -1555,6 +1564,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
ready: this.frozen,
domain: domain,
entity: pos === -1 ? domain : domain.slice(0, pos - domain.length),
skipCosmeticSurveying: false,
skipCosmeticFiltering: this.acceptedCount === 0,
cosmeticHide: [],
cosmeticDonthide: this.genericDonthide.slice(),
@ -1591,8 +1601,12 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
bucket.retrieve(hostname, r.cosmeticDonthide);
}
this.retrieveFromSelectorCache(hostname, 'cosmetic', r.cosmeticHide);
this.retrieveFromSelectorCache(hostname, 'net', r.netHide);
var cacheEntry = this.selectorCache[hostname];
if ( cacheEntry ) {
cacheEntry.retrieve('cosmetic', r.cosmeticHide);
cacheEntry.retrieve('net', r.netHide);
r.skipCosmeticSurveying = cacheEntry.cosmeticSurveyingMissCount > cosmeticSurveyingMissCountMax;
}
//quickProfiler.stop();

View File

@ -31,12 +31,14 @@ if ( typeof vAPI !== 'object' || typeof vAPI.domFilterer !== 'object' ) {
return;
}
var loggedSelectors = vAPI.loggedSelectors || {},
var df = vAPI.domFilterer,
loggedSelectors = vAPI.loggedSelectors || {},
matchedSelectors = [],
selectors, i, selector, entry, nodes, j;
selectors, i, selector;
// CSS-based selectors.
selectors = vAPI.domFilterer.simpleSelectors.concat(vAPI.domFilterer.complexSelectors);
// CSS selectors.
selectors = df.jobQueue[2]._0.concat(df.jobQueue[3]._0);
i = selectors.length;
while ( i-- ) {
selector = selectors[i];
@ -50,48 +52,16 @@ while ( i-- ) {
matchedSelectors.push(selector);
}
// `:has`-based selectors.
selectors = vAPI.domFilterer.simpleHasSelectors.concat(vAPI.domFilterer.complexHasSelectors);
i = selectors.length;
while ( i-- ) {
entry = selectors[i];
selector = entry.a + ':has(' + entry.b + ')';
if ( loggedSelectors.hasOwnProperty(selector) ) {
continue;
}
nodes = document.querySelectorAll(entry.a);
j = nodes.length;
while ( j-- ) {
if ( nodes[j].querySelector(entry.b) !== null ) {
loggedSelectors[selector] = true;
matchedSelectors.push(selector);
break;
}
}
}
// `:xpath`-based selectors.
var xpr = null,
xpathexpr;
selectors = vAPI.domFilterer.xpathSelectors;
i = selectors.length;
while ( i-- ) {
xpathexpr = selectors[i];
selector = ':xpath(' + xpathexpr + ')';
if ( loggedSelectors.hasOwnProperty(selector) ) {
continue;
}
xpr = document.evaluate(
'boolean(' + xpathexpr + ')',
document,
null,
XPathResult.BOOLEAN_TYPE,
xpr
);
if ( xpr.booleanValue ) {
loggedSelectors[selector] = true;
matchedSelectors.push(selector);
// Non-CSS selectors.
var logHit = function(node, job) {
if ( !job.raw || loggedSelectors.hasOwnProperty(job.raw) ) {
return;
}
loggedSelectors[job.raw] = true;
matchedSelectors.push(job.raw);
};
for ( i = 4; i < df.jobQueue.length; i++ ) {
df.runJob(df.jobQueue[i], logHit);
}
vAPI.loggedSelectors = loggedSelectors;

View File

@ -694,11 +694,10 @@ var cosmeticFilterMapper = (function() {
var filterMap = nodeToCosmeticFilterMap,
selectors, selector,
nodes, node,
entries, entry,
i, j;
// CSS-based selectors: simple one.
selectors = vAPI.domFilterer.simpleSelectors;
selectors = vAPI.domFilterer.job2._0;
i = selectors.length;
while ( i-- ) {
selector = selectors[i];
@ -716,7 +715,7 @@ var cosmeticFilterMapper = (function() {
}
// CSS-based selectors: complex one (must query from doc root).
selectors = vAPI.domFilterer.complexSelectors;
selectors = vAPI.domFilterer.job3._0;
i = selectors.length;
while ( i-- ) {
selector = selectors[i];
@ -730,72 +729,14 @@ var cosmeticFilterMapper = (function() {
}
}
// `:has()`-based selectors: simple ones.
entries = vAPI.domFilterer.simpleHasSelectors;
i = entries.length;
while ( i-- ) {
entry = entries[i];
selector = entry.a + ':has(' + entry.b + ')';
if (
filterMap.has(rootNode) === false &&
rootNode[matchesFnName](entry.a) &&
rootNode.querySelector(entry.b) !== null
) {
filterMap.set(rootNode, selector);
}
nodes = rootNode.querySelectorAll(entry.a);
j = nodes.length;
while ( j-- ) {
node = nodes[j];
if (
filterMap.has(node) === false &&
node.querySelector(entry.b) !== null
) {
filterMap.set(node, selector);
}
}
}
// `:has()`-based selectors: complex ones (must query from doc root).
entries = vAPI.domFilterer.complexHasSelectors;
i = entries.length;
while ( i-- ) {
entry = entries[i];
selector = entry.a + ':has(' + entry.b + ')';
nodes = document.querySelectorAll(entry.a);
j = nodes.length;
while ( j-- ) {
node = nodes[j];
if (
filterMap.has(node) === false &&
node.querySelector(entry.b) !== null
) {
filterMap.set(node, selector);
}
}
}
// `:xpath()`-based selectors.
var xpr;
entries = vAPI.domFilterer.xpathSelectors;
i = entries.length;
while ( i-- ) {
entry = entries[i];
selector = ':xpath(' + entry + ')';
xpr = document.evaluate(
entry,
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
xpr
);
j = xpr.snapshotLength;
while ( j-- ) {
node = xpr.snapshotItem(j);
if ( filterMap.has(node) === false ) {
filterMap.set(node, selector);
}
// Non-CSS selectors.
var runJobCallback = function(node, job) {
if ( filterMap.has(node) === false ) {
filterMap.set(node, job.raw);
}
};
for ( i = 4; i < vAPI.domFilterer.jobQueue.length; i++ ) {
vAPI.domFilterer.runJob(vAPI.domFilterer.jobQueue[i], runJobCallback);
}
};