From 928ab91ab8b72be1c962370b49a36fbe1e1ded94 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 19 Feb 2019 10:46:33 -0500 Subject: [PATCH] Add support to benchmark the dynamic filtering pane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From uBO's dev console, type: - `µBlock.sessionFirewall.benchmark();` Keep in mind that it's the temporary ruleset being benchmarked. --- src/js/dynamic-net-filtering.js | 31 ++++++++++++- src/js/static-net-filtering.js | 62 ++----------------------- src/js/utils.js | 82 +++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 59 deletions(-) diff --git a/src/js/dynamic-net-filtering.js b/src/js/dynamic-net-filtering.js index 5cce84101..c222556ca 100644 --- a/src/js/dynamic-net-filtering.js +++ b/src/js/dynamic-net-filtering.js @@ -528,7 +528,7 @@ Matrix.prototype.removeFromRuleParts = function(parts) { /******************************************************************************/ -var magicId = 1; +const magicId = 1; Matrix.prototype.toSelfie = function() { return { @@ -546,6 +546,35 @@ Matrix.prototype.fromSelfie = function(selfie) { /******************************************************************************/ +Matrix.prototype.benchmark = function() { + µBlock.loadBenchmarkDataset().then(requests => { + if ( Array.isArray(requests) === false || requests.length === 0 ) { + console.info('No requests found to benchmark'); + return; + } + console.info(`Benchmarking sessionFirewall.evaluateCellZY()...`); + const fctxt = µBlock.filteringContext.duplicate(); + const t0 = self.performance.now(); + for ( const request of requests ) { + fctxt.setURL(request.url); + fctxt.setTabOriginFromURL(request.frameUrl); + fctxt.setType(request.cpt); + this.evaluateCellZY( + fctxt.getTabHostname(), + fctxt.getHostname(), + fctxt.type + ); + } + const t1 = self.performance.now(); + const dur = t1 - t0; + console.info(`Evaluated ${requests.length} requests in ${dur.toFixed(0)} ms`); + console.info(`\tAverage: ${(dur / requests.length).toFixed(3)} ms per request`); + }); + return 'ok'; +}; + +/******************************************************************************/ + return Matrix; /******************************************************************************/ diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index fdd41469f..db6361a30 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -2690,74 +2690,20 @@ FilterContainer.prototype.getFilterCount = function() { /******************************************************************************/ -// The requests.json.gz file can be downloaded from: -// https://cdn.cliqz.com/adblocking/requests_top500.json.gz -// -// Which is linked from: -// https://whotracks.me/blog/adblockers_performance_study.html -// -// Copy the file into ./tmp/requests.json.gz -// -// If the file is present when you build uBO using `make-[target].sh` from -// the shell, the resulting package will have `./assets/requests.json`, which -// will be looked-up by the method below to launch a benchmark session. -// -// From uBO's dev console, launch the benchmark: -// µBlock.staticNetFilteringEngine.benchmark(); -// -// The advanced setting `consoleLogLevel` must be set to `info` to see the -// results in uBO's dev console, see: -// https://github.com/gorhill/uBlock/wiki/Advanced-settings#consoleloglevel -// -// The usual browser dev tools can be used to obtain useful profiling -// data, i.e. start the profiler, call the benchmark method from the -// console, then stop the profiler when it completes. -// -// Keep in mind that the measurements at the blog post above where obtained -// with ONLY EasyList. The CPU reportedly used was: -// https://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i7-6600U+%40+2.60GHz&id=2608 -// -// Rename ./tmp/requests.json.gz to something else if you no longer want -// ./assets/requests.json in the build. - FilterContainer.prototype.benchmark = function() { - new Promise(resolve => { - console.info(`Loading benchmark dataset...`); - const url = vAPI.getURL('/assets/requests.json'); - µb.assets.fetchText(url, details => { - if ( details.error !== undefined ) { - console.info(`Not found: ${url}`); - resolve(); - return; - } - console.info(`Parsing benchmark dataset...`); - const requests = []; - const lineIter = new µb.LineIterator(details.content); - while ( lineIter.eot() === false ) { - let request; - try { - request = JSON.parse(lineIter.next()); - } catch(ex) { - } - if ( request instanceof Object === false ) { continue; } - if ( !request.frameUrl || !request.url ) { continue; } - requests.push(request); - } - resolve(requests); - }); - }).then(requests => { + µb.loadBenchmarkDataset().then(requests => { if ( Array.isArray(requests) === false || requests.length === 0 ) { console.info('No requests found to benchmark'); return; } - console.info(`Benchmarking...`); - const fctxt = µb.filteringContext; + console.info(`Benchmarking staticNetFilteringEngine.matchString()...`); + const fctxt = µb.filteringContext.duplicate(); const t0 = self.performance.now(); for ( const request of requests ) { fctxt.setURL(request.url); fctxt.setDocOriginFromURL(request.frameUrl); fctxt.setType(request.cpt); - void this.matchString(fctxt); + this.matchString(fctxt); } const t1 = self.performance.now(); const dur = t1 - t0; diff --git a/src/js/utils.js b/src/js/utils.js index dcee74c28..f2d7fd0b4 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -605,3 +605,85 @@ return rem === 0 ? size : size + rem - 1; }, }; + +/******************************************************************************/ + +// The requests.json.gz file can be downloaded from: +// https://cdn.cliqz.com/adblocking/requests_top500.json.gz +// +// Which is linked from: +// https://whotracks.me/blog/adblockers_performance_study.html +// +// Copy the file into ./tmp/requests.json.gz +// +// If the file is present when you build uBO using `make-[target].sh` from +// the shell, the resulting package will have `./assets/requests.json`, which +// will be looked-up by the method below to launch a benchmark session. +// +// From uBO's dev console, launch the benchmark: +// µBlock.staticNetFilteringEngine.benchmark(); +// +// The advanced setting `consoleLogLevel` must be set to `info` to see the +// results in uBO's dev console, see: +// https://github.com/gorhill/uBlock/wiki/Advanced-settings#consoleloglevel +// +// The usual browser dev tools can be used to obtain useful profiling +// data, i.e. start the profiler, call the benchmark method from the +// console, then stop the profiler when it completes. +// +// Keep in mind that the measurements at the blog post above where obtained +// with ONLY EasyList. The CPU reportedly used was: +// https://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i7-6600U+%40+2.60GHz&id=2608 +// +// Rename ./tmp/requests.json.gz to something else if you no longer want +// ./assets/requests.json in the build. + +µBlock.loadBenchmarkDataset = (function() { + let datasetPromise; + let ttlTimer; + + return function() { + if ( ttlTimer !== undefined ) { + clearTimeout(ttlTimer); + ttlTimer = undefined; + } + + vAPI.setTimeout(( ) => { + ttlTimer = undefined; + datasetPromise = undefined; + }, 60000); + + if ( datasetPromise !== undefined ) { + return datasetPromise; + } + + datasetPromise = new Promise(resolve => { + console.info(`Loading benchmark dataset...`); + const url = vAPI.getURL('/assets/requests.json'); + µBlock.assets.fetchText(url, details => { + if ( details.error !== undefined ) { + datasetPromise = undefined; + console.info(`Not found: ${url}`); + resolve(); + return; + } + console.info(`Parsing benchmark dataset...`); + const requests = []; + const lineIter = new µBlock.LineIterator(details.content); + while ( lineIter.eot() === false ) { + let request; + try { + request = JSON.parse(lineIter.next()); + } catch(ex) { + } + if ( request instanceof Object === false ) { continue; } + if ( !request.frameUrl || !request.url ) { continue; } + requests.push(request); + } + resolve(requests); + }); + }); + + return datasetPromise; + }; +})();