From a3f6a4186a539dc2867b52e6e68f681246522388 Mon Sep 17 00:00:00 2001 From: gorhill Date: Thu, 30 Jun 2016 16:10:38 -0400 Subject: [PATCH] instrumenting content scripts to make for easy profiling when needed --- platform/chromium/vapi-client.js | 54 ++++++++++++++++++++++++++++++-- platform/firefox/vapi-client.js | 52 ++++++++++++++++++++++++++++++ src/js/contentscript.js | 39 ++++++++++++++++++----- 3 files changed, 134 insertions(+), 11 deletions(-) diff --git a/platform/chromium/vapi-client.js b/platform/chromium/vapi-client.js index 9fb54331f..9a4a34d38 100644 --- a/platform/chromium/vapi-client.js +++ b/platform/chromium/vapi-client.js @@ -62,12 +62,58 @@ if ( vAPI.sessionId ) { return; } -vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) + - Math.random().toString(36).slice(2); -vAPI.chrome = true; +/******************************************************************************/ + +vAPI.executionCost = { + start: function(){}, + stop: function(){} +}; +/* +vAPI.executionCost = { + tcost: 0, + tstart: 0, + nstart: 0, + level: 1, + start: function() { + if ( this.nstart === 0 ) { + this.tstart = window.performance.now(); + } + this.nstart += 1; + }, + stop: function(mark) { + this.nstart -= 1; + if ( this.nstart !== 0 ) { + return; + } + var tcost = window.performance.now() - this.tstart; + this.tcost += tcost; + if ( mark === undefined ) { + return; + } + var top = window === window.top; + if ( !top && this.level < 2 ) { + return; + } + var context = window === window.top ? ' top' : 'frame'; + var percent = this.tcost / window.performance.now() * 100; + console.log( + 'uBO cost (%s): %sms/%s%% (%s: %sms)', + context, + this.tcost.toFixed(1), + percent.toFixed(1), + mark, + tcost.toFixed(2) + ); + } +}; +*/ +vAPI.executionCost.start(); /******************************************************************************/ +vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) + + Math.random().toString(36).slice(2); +vAPI.chrome = true; vAPI.setTimeout = vAPI.setTimeout || self.setTimeout.bind(self); /******************************************************************************/ @@ -338,6 +384,8 @@ vAPI.shutdown.add(function() { // https://www.youtube.com/watch?v=rT5zCHn0tsg // https://www.youtube.com/watch?v=E-jS4e3zacI +vAPI.executionCost.stop('vapi-client.js'); + /******************************************************************************/ /******************************************************************************/ diff --git a/platform/firefox/vapi-client.js b/platform/firefox/vapi-client.js index f09577aaa..160bf07a7 100644 --- a/platform/firefox/vapi-client.js +++ b/platform/firefox/vapi-client.js @@ -53,6 +53,54 @@ self.rpc = self.rpc || function(){}; /******************************************************************************/ var vAPI = self.vAPI = self.vAPI || {}; + +/******************************************************************************/ + +vAPI.executionCost = { + start: function(){}, + stop: function(){} +}; +/* +vAPI.executionCost = vAPI.executionCost || { + tcost: 0, + tstart: 0, + nstart: 0, + level: 1, + start: function() { + if ( this.nstart === 0 ) { + this.tstart = window.performance.now(); + } + this.nstart += 1; + }, + stop: function(mark) { + this.nstart -= 1; + if ( this.nstart !== 0 ) { + return; + } + var tcost = window.performance.now() - this.tstart; + this.tcost += tcost; + if ( mark === undefined ) { + return; + } + var top = window === window.top; + if ( !top && this.level < 2 ) { + return; + } + var context = window === window.top ? ' top' : 'frame'; + var percent = this.tcost / window.performance.now() * 100; + console.log( + 'uBO cost (' + context + '): ' + + this.tcost.toFixed(1) + 'ms/' + + percent.toFixed(1) + '% (' + + mark + ': ' + tcost.toFixed(2) + 'ms)' + ); + } +}; +*/ +vAPI.executionCost.start(); + +/******************************************************************************/ + vAPI.firefox = true; vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) + Math.random().toString(36).slice(2); @@ -381,6 +429,10 @@ if ( window !== window.top ) { /******************************************************************************/ +vAPI.executionCost.stop('vapi-client.js'); + +/******************************************************************************/ + })(this); /******************************************************************************/ diff --git a/src/js/contentscript.js b/src/js/contentscript.js index 5132aa96b..154cde405 100644 --- a/src/js/contentscript.js +++ b/src/js/contentscript.js @@ -36,6 +36,8 @@ if ( typeof vAPI !== 'object' || vAPI.contentscriptInjected ) { throw new Error('Unexpected condition: aborting.'); } +vAPI.executionCost.start(); + vAPI.contentscriptInjected = true; vAPI.matchesProp = (function() { @@ -273,6 +275,9 @@ vAPI.domFilterer = { }, commitComplexSelectors: function() { + if ( this.complexSelectorsNodeSet === null ) { + return; + } var tstart = window.performance.now(), newNodeSet = new Set(); if ( this.complexGroupSelector === null ) { @@ -443,8 +448,6 @@ vAPI.domFilterer = { // support of Set(), uBO will skip committing complex selectors. if ( typeof window.Set === 'function' ) { df.complexSelectorsNodeSet = new Set(); - } else { - df.complexSelectorsCost = Number.MAX_VALUE; } // Theoretically, `:has`- and `:xpath`-based selectors may also need to @@ -528,6 +531,8 @@ var injectScripts = function(scripts) { /******************************************************************************/ var responseHandler = function(details) { + vAPI.executionCost.start(); + if ( details ) { if ( (vAPI.skipCosmeticFiltering = details.skipCosmeticFiltering) !== true && @@ -550,6 +555,8 @@ var responseHandler = function(details) { // process was fully initialized. When this happens, pages won't be // cleaned right after browser launch. vAPI.contentscriptInjected = details && details.ready; + + vAPI.executionCost.stop('domIsLoading/responseHandler'); }; /******************************************************************************/ @@ -832,6 +839,8 @@ if ( !vAPI.contentscriptInjected ) { return; } +vAPI.executionCost.start(); + /******************************************************************************/ // Cosmetic filtering. @@ -842,11 +851,6 @@ if ( !vAPI.contentscriptInjected ) { return; } - //console.debug('Start cosmetic filtering'); - - //var timer = window.performance || Date; - //var tStart = timer.now(); - // https://github.com/chrisaljoudi/uBlock/issues/789 // https://github.com/gorhill/uBlock/issues/873 // Be sure that our style tags used for cosmetic filtering are still applied. @@ -867,6 +871,8 @@ if ( !vAPI.contentscriptInjected ) { return; } + vAPI.executionCost.start(); + var result = response && response.result; if ( result ) { @@ -892,6 +898,8 @@ if ( !vAPI.contentscriptInjected ) { domFilterer.commit(contextNodes); contextNodes = []; + + vAPI.executionCost.stop('domIsLoaded/responseHandler'); }; var retrieveGenericSelectors = function() { @@ -1166,6 +1174,8 @@ if ( !vAPI.contentscriptInjected ) { var collapser = domCollapser; var addedNodesHandler = function() { + vAPI.executionCost.start(); + addedNodeListsTimer = null; if ( addedNodeListsTimerDelay < 100 ) { addedNodeListsTimerDelay += 25; @@ -1192,6 +1202,8 @@ if ( !vAPI.contentscriptInjected ) { classesAndIdsFromNodeList(selectNodes('[class],[id]')); retrieveGenericSelectors(); } + + vAPI.executionCost.stop('domIsLoaded/responseHandler'); }; // https://github.com/gorhill/uBlock/issues/873 @@ -1212,6 +1224,8 @@ if ( !vAPI.contentscriptInjected ) { // overhead of processing too few nodes too often and the delay of many // nodes less often. var domLayoutChanged = function(mutations) { + vAPI.executionCost.start(); + var removedNodeLists = false; var iMutation = mutations.length; var nodeList, mutation; @@ -1231,6 +1245,8 @@ if ( !vAPI.contentscriptInjected ) { if ( removedNodeListsTimerDelay !== 0 && removedNodeLists && removedNodeListsTimer === null ) { removedNodeListsTimer = vAPI.setTimeout(removedNodesHandler, removedNodeListsTimerDelay); } + + vAPI.executionCost.stop('domIsLoaded/domLayoutChanged'); }; //console.debug('Starts cosmetic filtering\'s mutations observer'); @@ -1265,9 +1281,10 @@ if ( !vAPI.contentscriptInjected ) { (function() { var onResourceFailed = function(ev) { - //console.debug('onResourceFailed(%o)', ev); + vAPI.executionCost.start(); domCollapser.add(ev.target); domCollapser.process(); + vAPI.executionCost.stop('domIsLoaded/onResourceFailed'); }; document.addEventListener('error', onResourceFailed, true); @@ -1319,6 +1336,7 @@ if ( !vAPI.contentscriptInjected ) { var messaging = vAPI.messaging; var onMouseClick = function(ev) { + vAPI.executionCost.start(); var elem = ev.target; while ( elem !== null && elem.localName !== 'a' ) { elem = elem.parentElement; @@ -1331,6 +1349,7 @@ if ( !vAPI.contentscriptInjected ) { y: ev.clientY, url: elem !== null ? elem.href : '' }); + vAPI.executionCost.stop('domIsLoaded/onMouseClick'); }; document.addEventListener('mousedown', onMouseClick, true); @@ -1343,6 +1362,8 @@ if ( !vAPI.contentscriptInjected ) { /******************************************************************************/ +vAPI.executionCost.stop('domIsLoaded'); + }; /******************************************************************************/ @@ -1354,3 +1375,5 @@ if ( document.readyState !== 'loading' ) { } else { document.addEventListener('DOMContentLoaded', domIsLoaded); } + +vAPI.executionCost.stop('contentscript.js');