javascript - node.js 中 setInterval() 的奇怪行为(仅限 Windows,适用于 Linux)

标签 javascript node.js linux windows setinterval

我一直在使用 windows 机器上的 node.js 遇到一些奇怪的问题,这些问题在 linux 机器上不会发生。

在低延迟设置(< 100 毫秒)下使用 setInterval() 函数时:本质上,所提供函数的调用频率低于我的预期,而且调用的方式非常一致。使用我在下面快速编写的示例代码时,即使在相同的硬件上运行,Windows 机器似乎也会给出与 Linux 机器始终不同的结果。

//should be time in MS between executions
var delay = 10;

//how many seconds to run the test
var testPeriods = 10;

var counter = 0;
var startTime = new Date().getTime();

var interval = setInterval(() => {
    ++counter;
    if (new Date().getTime() >= startTime+1000*testPeriods) {
        console.log('Mean Function Calls per Second:', counter/testPeriods);
        clearInterval(interval);
    }
}, delay);

一些测试数据,来 self 的双启动 linux 和 windows 的电脑:

Delay (ms) | Expected | Linux result | Windows result
-----------+----------+--------------+---------------
       100 |       10 |         10.0 |            9.2
        50 |       20 |         20.0 |           16.0
        25 |       40 |         39.8 |           32.0
        10 |      100 |         98.4 |           63.8

您会注意到,在较低的延迟设置之前,Linux 结果几乎完美匹配,甚至它们也相距不远。另一方面,窗口结果远远不够。

我认为与 linux 版本相比,node 的 windows 版本可能优化不佳。所以起初,我假设我提供的函数执行时间太长,从而延迟了下一次执行。然而,情况似乎并非如此。毕竟,如果我假设所提供的函数无论如何都需要类似的时间来执行,那么我知道 Windows 机器可以在最低延迟设置下每秒最多执行 63 次。那么为什么它只执行了 ~32 次,而它应该执行 ~40 次(延迟 @ 25ms)?

如果有人能告诉我为什么会发生这种情况或我做错了什么,我将不胜感激。

编辑:根据@jfriend00 的建议简化代码,并更新测试结果以匹配。

最佳答案

调用一段预定代码的速度取决于操作系统的定时器中断间隔。根据操作系统的不同,此设置称为 tickjiffy。在某些操作系统上,它是可配置的。

操作系统会定期运行自己的代码来进行检查,例如让进程轮流使用 CPU、清理内存等。为此,操作系统会设置一个定时器中断(实际上它就像 setInterval 而已在硬件级别)运行自己的代码。

这实际上是操作系统如何设法运行比可用内核更多的进程/线程,并且正是这种机制还在操作系统级别的 javascript 中驱动 setIntervalsetTimeout。所以基本上线程和setInterval都使用相同的操作系统机制,唯一的区别是线程可以同时使用多个内核,而setInterval只能使用与主js相同的内核线程。

设置tick 的频率需要权衡取舍。将 tick 设置得非常短将使您的操作系统更加实时,因为事件处理的延迟会大大减少。然而,这也意味着您的操作系统代码使用了更高百分比的 CPU 时间,留给您的应用程序的时间更少。将 tick 设置得更长会给您的应用更多的 CPU 时间,从而给您更多的吞吐量。

实际上我对您的结果感到有点惊讶。多年前(2000 年代初)Linux 上的默认 jiffy 设置相当长,因为 Linux 针对服务器使用进行了更多优化,因此针对吞吐量进行了优化。另一方面,Windows 的 tick 更短,因为 Windows 针对玩游戏和运行图形应用程序等实时任务进行了更多优化。也许这些年来情况发生了变化。

所以是的,如果你想要跨平台的一致性,有一个最小的 setInterval 时间可以跨操作系统工作。但是我猜 10ms 就足够了,因为这是我多年来的经验(1ms 显然会显示各种操作系统的不同行为)。如果现在 10 毫秒不起作用,您可以尝试更长的间隔,例如 50 毫秒‡ 或 100 毫秒。

‡ note: 50ms or 20fps is the update interval of radio control transmitters so it is real-time enough for human reflexes to fly planes, helicopters and drones without crashing

关于javascript - node.js 中 setInterval() 的奇怪行为(仅限 Windows,适用于 Linux),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65177373/

相关文章:

javascript - 在 Typescript 中输入内容时遇到问题

linux - 在日志文件中保留 60 行

javascript - 让 NodeJS 服务器通过 USB 自动检测连接的设备

javascript - 仅执行 'onscroll'函数一次

javascript - 单击时淡出,除非单击输入元素

javascript - 我的cookie消失了

javascript - axios不捕获数据并发送给客户端

javascript - 每次事件后创建目录

javascript - 如何从 NodeJS 的 https 获取正文?

linux - 进程因 -9 中止而终止?