JavaScript中是否有微秒级分辨率的计时函数?
我知道在Chrome浏览器中有一个名为timer.js的解决方案,但我希望其他浏览器也有类似的解决方案,如Firefox、Safari、Opera、Epiphany和Konqueror等。我对支持IE不感兴趣,但包括IE在内的答案也可以考虑。
(鉴于JS中毫秒级计时的精度较低,我对这个问题并不抱有太大期望!)
更新:timer.js声称具有微秒级分辨率,但实际上只是将毫秒读数乘以1,000。通过测试和代码检查已验证。令人失望。:[
JavaScript中是否有微秒级分辨率的计时函数?
我知道在Chrome浏览器中有一个名为timer.js的解决方案,但我希望其他浏览器也有类似的解决方案,如Firefox、Safari、Opera、Epiphany和Konqueror等。我对支持IE不感兴趣,但包括IE在内的答案也可以考虑。
(鉴于JS中毫秒级计时的精度较低,我对这个问题并不抱有太大期望!)
更新:timer.js声称具有微秒级分辨率,但实际上只是将毫秒读数乘以1,000。通过测试和代码检查已验证。令人失望。:[
window.performance.now()
。
now()
比传统的Date.getTime()
更好,有两个重要的方面:
now()
是一个双精度数值,具有亚毫秒分辨率,表示自页面导航开始以来的毫秒数。它返回小数部分中的微秒数(例如,1000.123的值为1秒和123微秒)。
now()
单调递增。这很重要,因为Date.getTime()
可能会在后续调用中向前或向后跳跃。值得注意的是,如果操作系统的系统时间被更新(例如原子钟同步),Date.getTime()
也会被更新。now()
保证始终单调递增,因此不受操作系统的系统时间影响——它将始终是挂钟时间(假设您的挂钟不是原子钟...)。
now()
可以在几乎所有使用 new Date.getTime()
、+ new Date
以及 Date.now()
的地方使用。唯一的例外是,Date
和 now()
的时间不能混用,因为 Date
基于 unix-epoch(自1970年以来的毫秒数),而 now()
是自您页面导航开始以来的毫秒数(因此比 Date
小得多)。
now()
支持 Chrome 稳定版、Firefox 15+ 和 IE10。还有几个 polyfills 可用。
注意:在使用 Web Workers 时,window
变量不可用,但仍然可以使用 performance.now()
。
new Date.getTime()
不是正确的语法。应该使用new Date().getTime()
。 - The Qodesmithconsole.log
这样昂贵的操作,我在一台好机器上也得到了10%的冲突)很难辨认,但请复制此处所有突出显示的代码:last=-11; same=0; runs=100; for(let i=0;i<runs;i++) { let now = performance.now(); console.log('.'); if (now === last) { same++; } last = now; } console.log(same, 'were the same');
- bladnman然而...如果由于异常情况只能对特定测试进行一次基准测试,我发现通过以下方法可以获得0.1(有时为0.01毫秒)的精度:
初始化/校准:
对一次基准测试进行亚毫秒精度:
警告:不建议在 Web 浏览器中使用繁忙循环,但幸运的是,这些繁忙循环每次只运行不到 1 毫秒,并且只运行很少的次数。
像 JIT 编译和 CPU 波动等变量会带来巨大的不准确性,但如果你运行多个初始化过程,你将获得完全的动态重新编译,并且最终计数器会稳定在非常准确的值。确保所有繁忙循环对于所有情况都是完全相同的功能,以便繁忙循环的差异不会导致结果差异。确保在开始信任结果之前,执行所有代码行多次,以允许 JIT 编译器已经稳定为全动态重新编译(dynarec)。
实际上,我亲眼见证了某些系统精度接近微秒,但我还不太相信它。但是,在一个空闲的四核系统上,只有我一个浏览器页面时,0.1 毫秒的精度似乎非常可靠。我找到了一个科学测试案例,我只能做一次通过(由于出现独特的变量),并且需要精确计时每个通过,而不是平均多次重复通过,这就是我这样做的原因。
我进行了几次预处理和虚拟处理(也为了解决 dynarec),以验证可靠的 0.1 毫秒精度(保持数秒钟稳定),然后将手离开键盘/鼠标,当基准测试发生时,然后进行了几次后处理以验证可靠的 0.1 毫秒精度(再次保持稳定)。这还验证了类似电源状态更改或其他事物是否在前后之间发生,干扰结果。在每个基准测试通过之间重复进行预测试和后测试。
总之,我相当确定中间的结果是准确的。当然没有保证,但这表明,在某些情况下,Web 浏览器中的准确小于 0.1 毫秒的精度是可能的。
这种方法只在非常、非常特定的情况下有用。即使如此,它也无法百分之百地无限保证,但当与多层内部和外部验证相结合时,可以获得相当可靠的准确性,甚至是科学准确性。
Date.now()
或者+new Date()
。但现在我们有了performance.now()
。虽然你已经找到一些很酷的方法来突破更多的能力,但这个回答基本上已经过时了。此外,请不要推荐任何与忙等待相关的内容。就是不要这样做。我们不需要更多的这种东西。 - Steven Lu下面是一个示例,展示了我用于 node.js 的高分辨率计时器:
function startTimer() {
const time = process.hrtime();
return time;
}
function endTimer(time) {
function roundTo(decimalPlaces, numberToRound) {
return +(Math.round(numberToRound + `e+${decimalPlaces}`) + `e-${decimalPlaces}`);
}
const diff = process.hrtime(time);
const NS_PER_SEC = 1e9;
const result = (diff[0] * NS_PER_SEC + diff[1]); // Result in Nanoseconds
const elapsed = result * 0.0000010;
return roundTo(6, elapsed); // Result in milliseconds
}
使用方法:
const start = startTimer();
console.log('test');
console.log(`Time since start: ${endTimer(start)} ms`);
通常情况下,您可以使用以下方法:
console.time('Time since start');
console.log('test');
console.timeEnd('Time since start');
console.timeEnd()
的值以便将定时器结果相加。虽然可以这样做,但它会变得混乱,因为您必须注入您的迭代变量的值,如i
,并设置一个条件来检测循环是否完成。 const num = 10;
console.time(`Time til ${num}`);
for (let i = 0; i < num; i++) {
console.log('test');
if ((i+1) === num) { console.timeEnd(`Time til ${num}`); }
console.log('...additional steps');
}
引用:https://nodejs.org/api/process.html#process_process_hrtime_time
该方法返回一个包含当前高精度实际时间的数组,其中第一项是秒数,第二项是纳秒数。这个方法主要用于衡量程序运行时间和性能优化。