Could someone please explain why the script, below with the setTimeout
mand, takes a lot longer to execute (400-500 ms) in Greasemonkey than it does in the Firefox console, where it's exactly 100 ms?
var start = new Date ().getTime ();
console.log (
new Date ().getHours ()+" : " + new Date ().getMinutes ()
+ " : " + new Date ().getSeconds () + " : "
+ new Date ().getMilliseconds ()
);
setTimeout (foo,100);
//foo ();
function foo () {
var time = new Date () - start;
console.log ("Execution time: " + time + "ms");
}
It's strange, because if I switch setTimeout(foo,100)
for a pure foo()
, both Greasemonkey and Firefox console execute it lightning fast (~10 ms).
Could someone please explain why the script, below with the setTimeout
mand, takes a lot longer to execute (400-500 ms) in Greasemonkey than it does in the Firefox console, where it's exactly 100 ms?
var start = new Date ().getTime ();
console.log (
new Date ().getHours ()+" : " + new Date ().getMinutes ()
+ " : " + new Date ().getSeconds () + " : "
+ new Date ().getMilliseconds ()
);
setTimeout (foo,100);
//foo ();
function foo () {
var time = new Date () - start;
console.log ("Execution time: " + time + "ms");
}
It's strange, because if I switch setTimeout(foo,100)
for a pure foo()
, both Greasemonkey and Firefox console execute it lightning fast (~10 ms).
- Try removing the first console log – juvian Commented Mar 30, 2014 at 0:28
1 Answer
Reset to default 6Actually, on my scratch system (Win XP, FF 28.0, GM 1.15) this has very little to do with Greasemonkey and everything to do with (A) the console, and (B) what else Firefox and/or your machine is doing.
JavaScript timers are notoriously bad. (See, also, "Accuracy of JavaScript Time" by John Resig.)
Your results are based off a very small sample size and are not enough data to begin to see an accurate picture. Also browsers, and Greasemonkey, have been changing in regards to this problem, so your versions may differ.
If we use an interval, EG:
setInterval (foo, 100);
function foo () {
var time = new Date () - start;
console.log ("Execution time: " + time + "ms");
}
then we can start collecting some statistical data and see what might be going on.
Refining that code and adding statistics gives a userscript like this:
// ==UserScript==
// @name _Greasemonkey timing test
// @include https://stackoverflow./questions/22738493/*
// @grant none
// ==/UserScript==
// @grant GM_addStyle
/*--- Test:
Both grant modes
FF console
Firebug console
Embedded in page.
*/
var numMeasurements = 100;
var measurementList = [];
var startDate = new Date ();
var startTime = startDate.getTime ();
console.log (
startDate.getHours ()+ " : " + startDate.getMinutes () + " : "
+ startDate.getSeconds () + " : " + startDate.getMilliseconds ()
);
var startDate = new Date (); //-- Record time just before interval start.
//setTimeout (timelog, 100);
/*--- WARNING: for delays less than about 50, system "granularity" and
overhead effects will distort the results even more.
*/
var logTimer = setInterval (timelog, 100);
function timelog () {
timelog.numloops = timelog.numloops || 0;
if (timelog.numloops >= numMeasurements) {
console.log ('===> Reached ' + timelog.numloops + ' loops.');
clearInterval (logTimer);
//--- Calculate stats:
var stats = {};
stats.min = Number.MAX_VALUE; //-- Always start at opposite
stats.max = Number.MIN_VALUE;
stats.sum = 0;
stats.mean = 0;
stats.sumSqrs = 0;
stats.stdDev = 0;
stats.N = measurementList.length;
for (var J = 0; J < stats.N; ++J) {
var measVal = measurementList[J];
stats.sum += measVal;
stats.sumSqrs += measVal * measVal;
if (measVal > stats.max) stats.max = measVal;
if (measVal < stats.min) stats.min = measVal;
}
stats.mean = stats.sum / stats.N;
stats.stdDev = Math.sqrt (
(stats.sumSqrs / stats.N) - (stats.mean * stats.mean)
);
//--- Display stats:
var decsToDisplay = 1;
console.log (' Measurements: ' + stats.N);
console.log (' Average: ' + stats.mean.toFixed (decsToDisplay) );
console.log (' Min to Max: ' + stats.min + ' to ' + stats.max);
console.log ('Std Deviation: ' + stats.stdDev.toFixed (decsToDisplay) );
}
else {
timelog.numloops++;
var timeNow = new Date ();
var timeDif = timeNow - startDate;
measurementList.push (timeDif);
console.log (
'==> Execution time ('
//-- Left-pad value for more legible column, 3 chars wide.
+ (" " + timelog.numloops).slice (-3) + '): '
//-- Left-pad value for more legible column, 4 chars wide.
+ (" " + timeDif).slice (-4) + ' ms '
, timeNow.getTime ()
);
startDate = timeNow;
}
}
Install the script and/or you can see this code in action at jsFiddle.
To see if Greasemonkey is a factor, we should test at least these scenarios:
- Code in the Firefox console.
- Code in a webpage both to the console and with the consoles closed.
- Code in a Greasemonkey script with sandbox active (
@grant GM_addStyle
set). - Code in a Greasemonkey script with
@grant none
active. - Code in the Firebug console.
Ideally, the web page and system circumstances should remain as constant as possible.
Testing with a 100 ms delay and a 100 samples (probably the minimum values for meaningful data), I get (all values in milliseconds):
//-- These first were run against stackoverflow./q/22738493 Std Condition Min Max Avg Deviation -------------------------- --- --- ----- --------- Firefox console, run 1: 0 518 138.9 133.2 Firefox console, run 2: 1 466 215.4 209.6 Firebug console, run 1: 1 144 100.5 21.8 Firebug console, run 2: 3 209 100.9 25.2 GM to FF cons, in sandbox: 0 398 135.4 112.9 GM to FF cons, @grant none 1: 0 387 125.3 97.4 GM to FF cons, @grant none 2: 0 563 145.2 122.0 GM to Firebug console: 38 401 109.4 49.1 //-- These were run against jsfiddle/caL94/2 jsFiddle to FF console 1: 2 375 113.3 82.5 jsFiddle to FF console 2: 1 575 169.7 171.1 jsFiddle to Firebug console: 27 219 103.5 24.9 jsFiddle, consoles closed 1: 0 530 105.3 57.2 jsFiddle, consoles closed 2: 5 195 100.0 21.9
From these numbers, it should be clear that:
- JavaScript timers are no good for precision timing. (But they probably are adequate for most practical web-page uses.)
- Timing code in Greasemonkey performs just as well as code running in the Firebug console or not logging to any console.
- The real big hit is logging to Firefox's console (CtrlShiftK) -- which radically decreases timer accuracy.
- Computer and browser (and even webpage) state all impact accuracy, and repeatability, to a large degree.
- Also, remember that browsers throttle javascript timers if you switch away from the tab (loses focus).
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745252589a4618767.html
评论列表(0条)