【问题标题】:setTimeout is precise on Linux but not on Windows?setTimeout 在 Linux 上准确,但在 Windows 上不准确?
【发布时间】:2019-09-15 09:28:28
【问题描述】:

我有一个简单的 setTimeout 用法:

var oldDate = new Date().getTime();

setInterval(function(){
    var newDate = new Date().getTime();

    console.log(newDate - oldDate, 'ms');

    oldDate = newDate;
}, 7);

这在带有 Node(v10.15.2) 的 Linux 系统上打印:

8 'ms'
6 'ms'
8 'ms'
7 'ms'
8 'ms'
8 'ms'

但是在带有 Node(v10.15.1) 的 Windows 系统上:

21 'ms'
22 'ms'
20 'ms'
20 'ms'
17 'ms'
23 'ms'
18 'ms'
20 'ms'
22 'ms'
17 'ms'
17 'ms'
22 'ms'
19 'ms'
20 'ms'
23 'ms'
19 'ms'
30 'ms'

这绝对是一团糟,而且运行非常随机。

我需要一个精确且无阻塞的计时器。在 linux 中它就像一个魅力,但我很好奇,为什么它在 windows 中如此糟糕?

谢谢!

【问题讨论】:

  • 旁注:new Date().getTime() 更简单、更高效的版本是Date.now()
  • 在 Javascript 中没有精确的、抢先的计时器这样的东西。定时器回调是基于事件的。当计时器触发时,它会在事件队列中插入一个事件。该事件将在轮到它时运行,当在它之前发生的其他事件完成处理时。这可能接近也可能不接近计时器的分配时间。
  • 这看起来有点像X/Y problem。为什么你需要它比上面的更精确?
  • 实际上我正在制作一个需要稳定运行 60fps 的游戏服务器,所以我需要一个稳定的计时器 :) @T.J.Crowder

标签: node.js timer settimeout


【解决方案1】:

您不能使用计时器子系统进行精确计时。

了解这一点很重要,即使在 Linux 上,只要您的 Node.js 实例的主线程从不忙于做其他事情,例如处理 I/O 完成或运行您的某些 JavaScript 逻辑,它只会是“精确的”。 Node.js 程序中只有一个主线程(您可以通过Worker 拥有其他线程),它处理 I/O 完成回调和您的代码所做的任何其他事情(除非它在工作线程上)。 setTimeout/setInterval 在任务队列中安排正常任务,该队列还保存其他任务(例如,I/O 完成)。

如果您真的需要如此精确的计时,您可能至少需要将其移至工作线程,即使那样它也可能不精确。如果没有,您可能会更接近setImmediate 循环。如果这还不够接近,您可能需要在工作线程中忙等待(这将与 CPU 核心挂钩,但至少不会与主线程挂钩)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多