实际上,在我的临时系统(Win XP、FF 28.0、GM 1.15)上,这与 Greasemonkey 关系不大,而与 (A) 控制台和 (B) Firefox 和/或您的机器正在执行的其他操作有关。
JavaScript 定时器是出了名的糟糕 https://stackoverflow.com/q/196027/331508。 (也可以看看,John Resig 的“JavaScript 时间的准确性” http://ejohn.org/blog/accuracy-of-javascript-time/.)
您的结果基于非常小的样本量,并且没有足够的数据来开始看到准确的情况。此外,浏览器和 Greasemonkey 已针对此问题进行了更改,因此您的版本可能会有所不同。
如果我们使用区间,EG:
setInterval (foo, 100);
function foo () {
var time = new Date () - start;
console.log ("Execution time: " + time + "ms");
}
然后我们就可以开始收集一些统计数据,看看会发生什么。
完善该代码并添加统计信息可以得到如下的用户脚本:
// ==UserScript==
// @name _Greasemonkey timing test
// @include https://stackoverflow.com/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;
}
}
安装脚本和/或者您可以在 jsFiddle 中查看此代码的实际运行情况 http://jsfiddle.net/caL94/2/.
要了解 Greasemonkey 是否是一个因素,我们应该进行测试at least这些场景:
- Firefox 控制台中的代码。
- 在控制台和关闭控制台的情况下在网页中编写代码。
- 沙箱处于活动状态的 Greasemonkey 脚本中的代码(
@grant GM_addStyle
set).
- Greasemonkey 脚本中的代码
@grant none
active.
- Firebug 控制台中的代码。
理想情况下,网页和系统环境应尽可能保持不变。
使用 100 毫秒延迟和 100 个样本(可能是有意义数据的最小值)进行测试,我得到(所有值以毫秒为单位):
//-- These first were run against stackoverflow.com/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.net/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
从这些数字应该可以清楚地看出:
-
JavaScript 计时器不利于精确计时。(但它们可能足以满足大多数实际的网页用途。)
- Greasemonkey 中的计时代码的执行效果与在 Firebug 控制台中运行或不记录到任何控制台的代码一样好。
- The real big hit is logging to Firefox's console (CtrlShiftK) -- which radically decreases timer accuracy.
- 计算机和浏览器(甚至网页)状态都在很大程度上影响准确性和可重复性。
- 另外,请记住如果您离开选项卡,浏览器会限制 JavaScript 计时器 https://stackoverflow.com/q/15871942/331508(失去焦点)。