gpt4 book ai didi

javascript - setTimeout 花费的时间比应该的长

转载 作者:行者123 更新时间:2023-11-29 17:09:13 25 4
gpt4 key购买 nike

有人能解释一下为什么下面带有 setTimeout 命令的脚本在 Greasemonkey 中的执行时间(400-500 毫秒)比在 Firefox 控制台中的执行时间要长很多(400-500 毫秒),而在 Firefox 控制台中恰好是 100多发性硬化症?

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");
}

这很奇怪,因为如果我将 setTimeout(foo,100) 切换为纯 foo(),Greasemonkey 和 Firefox 控制台都会以闪电般的速度执行它(~10 毫秒).

最佳答案

实际上,在我的临时系统(Win XP、FF 28.0、GM 1.15)上,这与 Greasemonkey 几乎没有关系,而与 (A) 控制台和 (B) 还有什么 Firefox 和/或您的机器有关正在做。

JavaScript timers are notoriously bad . (另请参阅 "Accuracy of JavaScript Time" by John Resig。)

您的结果基于非常小的样本量,并且没有足够的数据来开始查看准确的图片。浏览器和 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;
}
}


安装脚本和/或者你可以 see this code in action at jsFiddle .

要查看 Greasemonkey 是否是一个因素,我们应该至少测试这些场景:

  1. Firefox 控制台中的代码。
  2. 在控制台和关闭控制台的网页中编写代码。
  3. 在激活沙箱的 Greasemonkey 脚本中编写代码(@grant GM_addStyle 设置)。
  4. 在激活 @grant none 的 Greasemonkey 脚本中编写代码。
  5. Firebug 控制台中的代码。

理想情况下,网页和系统环境应尽可能保持不变。

使用 100 毫秒延迟和 100 个样本(可能是有意义数据的最小值)进行测试,我得到(所有值以毫秒为单位):

//-- These first were run against stackoverflow.com/q/22738493                                                  StdCondition                      Min  Max   Avg   Deviation--------------------------     ---  ---  -----  ---------Firefox console, run 1:          0  518  138.9    133.2Firefox console, run 2:          1  466  215.4    209.6Firebug console, run 1:          1  144  100.5     21.8Firebug console, run 2:          3  209  100.9     25.2GM to FF cons, in sandbox:       0  398  135.4    112.9GM to FF cons, @grant none 1:    0  387  125.3     97.4GM to FF cons, @grant none 2:    0  563  145.2    122.0GM to Firebug console:          38  401  109.4     49.1//-- These were run against jsfiddle.net/caL94/2jsFiddle to FF console 1:        2  375  113.3     82.5jsFiddle to FF console 2:        1  575  169.7    171.1jsFiddle to Firebug console:    27  219  103.5     24.9jsFiddle, consoles closed 1:     0  530  105.3     57.2jsFiddle, consoles closed 2:     5  195  100.0     21.9


从这些数字中可以清楚地看出:

  1. JavaScript 计时器不利于精确计时。(但它们可能足以满足大多数实际网页使用。)
  2. Greasemonkey 中的计时代码与在 Firebug 控制台中运行或不登录任何控制台的代码执行得一样好。
  3. 真正的大成功是登录到 Firefox 的控制台(CtrlShiftK)——这从根本上降低了计时器的准确性。
  4. 计算机和浏览器(甚至网页)在很大程度上说明所有影响准确性和可重复性。
  5. 此外,请记住 browsers throttle javascript timers if you switch away from the tab (失去焦点)。

关于javascript - setTimeout 花费的时间比应该的长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22738493/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com