JavaScript中的微秒计时

JavaScript中的微秒计时,javascript,Javascript,JavaScript中是否有微秒分辨率的计时函数 我知道Chrome的解决方案,并希望能为其他友好浏览器提供解决方案,如Firefox、Safari、Opera、Epiphany、Konqueror等。我对支持任何IE都不感兴趣,但欢迎提供包括IE在内的答案 (考虑到JS中毫秒计时的准确性很差,我不会屏住呼吸的!) 更新:timer.js宣传微秒分辨率,但它只是将毫秒读数乘以1000。通过测试和代码检查进行验证。失望的[一般来说,答案是“不”。如果您在某些服务器端环境(即,不是在浏览器中)中使用

JavaScript中是否有微秒分辨率的计时函数

我知道Chrome的解决方案,并希望能为其他友好浏览器提供解决方案,如Firefox、Safari、Opera、Epiphany、Konqueror等。我对支持任何IE都不感兴趣,但欢迎提供包括IE在内的答案

(考虑到JS中毫秒计时的准确性很差,我不会屏住呼吸的!)

更新:timer.js宣传微秒分辨率,但它只是将毫秒读数乘以1000。通过测试和代码检查进行验证。失望的[

一般来说,答案是“不”。如果您在某些服务器端环境(即,不是在浏览器中)中使用JavaScript,那么所有赌注都是无效的,您可以尝试做任何您想做的事情


编辑-这个答案很古老;标准已经进步,新的工具可以作为精确时间问题的解决方案。尽管如此,应该记住,在真正的实时操作系统领域之外,普通非特权代码对其访问计算资源的控制有限。衡量性能是非常重要的与预测性能不同(必然如此)。

现在有一种新的测量javascript中微秒的方法:

然而,在过去,我发现了一种粗糙的方法,可以用毫秒计时器在JavaScript中获得0.1毫秒的精度。不可能?不可能。继续阅读:

我正在做一些高精度的实验,需要自检定时器的精度,发现在某些系统的某些浏览器上,我能够可靠地获得0.1毫秒的精度

我发现,在现代GPU加速的快速系统上的web浏览器中(例如i7四核,其中有几个核是空闲的,只有浏览器窗口)--我现在可以相信计时器是毫秒级的。事实上,它在空闲的i7系统上变得如此精确,我已经能够可靠地获得完全相同的毫秒,超过1000次尝试。只有当我尝试加载额外的网页或其他事情时,毫秒级的精确度才会降低(我能够通过做前后时间检查成功地捕捉到自己的精度下降,看看我的处理时间是否突然延长到1毫秒或更多毫秒——这有助于我使可能受到CPU波动太不利影响的结果无效)

它在i7四核系统上的一些GPU加速浏览器中变得如此精确(当浏览器窗口是唯一的窗口时),我发现我希望能够访问JavaScript中的0.1ms精度计时器,因为现在某些高端浏览系统上的精度终于达到了,这样的计时器精度对于需要高精度的特定类型的小应用程序来说是值得的,并且应用程序能够自我验证精度偏差

显然,如果要进行多次传递,只需运行多次传递(例如10次传递),然后除以10即可获得0.1毫秒的精度。这是获得更高精度的常用方法——进行多次传递并将总时间除以传递数

然而,如果由于异常独特的情况,我只能通过一次特定测试的基准测试,我发现通过这样做,我可以获得0.1(有时是0.01ms)的精度:

初始化/校准:

  • 运行忙循环以等待计时器增加到下一毫秒(将计时器与下一毫秒间隔的开始对齐)。此忙循环持续不到一毫秒
  • 在等待计时器递增时,运行另一个忙循环递增计数器。计数器告诉您一毫秒内发生了多少计数器递增。此忙循环持续一整毫秒
  • 重复上述步骤,直到数字变得非常稳定(加载时间、JIT编译器等).4.注意:数字的稳定性为您提供了在空闲系统上可达到的精度。如果需要自检精度,您可以计算方差。某些浏览器上的方差较大,而其他浏览器上的方差较小。速度较快的系统上的方差较大,速度较慢的系统上的方差较小。一致性也会有所不同。您可以区分哪个浏览器SER比其他系统更一致/准确。较慢的系统和繁忙的系统会导致初始化过程之间的差异更大。如果浏览器没有给您足够的精度以允许进行0.1ms或0.01ms的测量,则可以显示警告消息。计时器倾斜可能是个问题,但某些整数毫秒某些系统上的nd定时器增量相当准确(在点上非常准确),这将导致非常一致的校准值,您可以信任
  • 保存最终计数器值(或最近几次校准通过的平均值)
  • 基准测试一次通过至亚毫秒精度:

  • 运行忙循环以等待计时器增加到下一毫秒(将计时器与下一毫秒间隔的开始对齐)。此忙循环持续不到一毫秒
  • 执行要精确基准时间的任务
  • 检查计时器。这将为您提供整数毫秒
  • 在等待计时器递增时,运行最后一个忙循环递增计数器。此忙循环持续不到一毫秒
  • 将此计数器值除以初始化的原始计数器值
  • 现在你得到了毫秒的小数部分
  • 警告:不建议在web浏览器中使用忙循环,但幸运的是,这些忙循环每次运行的时间都不到1毫秒,并且只运行很少几次

    JIT编译和CPU波动等变量会增加大量的不精确性,但如果运行多个初始化过程,则会进行完全的动态重新编译,最终计数器会稳定到非常精确的程度。请确保所有忙循环在所有情况下都是完全相同的函数,这样忙循环中的差异就可以消除
     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');
    
     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');
     }