每秒奇怪的结果测试操作

Weird result testing operation per sec

我在节点 8.11 上 运行 这个测试脚本:

let end = false;

let i = 0;
setInterval(() => { i++; }).unref();


let k = 0;
async function loop() {
  k++
  if (end === false)
    setImmediate(loop);
}

console.time('test');
loop()
  .then(() => {
    setTimeout(() => {
      end = true;
      console.log('interval', i);
      console.log('recursion', k);
      console.timeEnd('test');
    }, 1000);
  })

输出为:

interval 997
recursion 824687
test: 1001.831ms

但是,如果我评论这两行:

  // if (end === false)
  //  setImmediate(loop);

结果是:

interval 537
recursion 1
test: 1003.882ms

我认真研究了 phases of nodejs 但我不明白为什么 setImmediate 会影响区间函数的结果。

你有什么解释吗?

谢谢

那是因为nodejs上的定时器在某种意义上并不精确,它们只是事件循环中的事件,因此它们无法确切知道它们何时会被触发,这就是为什么setTimeout说它至少会执行在您提供的时间之后。

The timeout interval that is set cannot be relied upon to execute after that exact number of milliseconds. This is because other executing code that blocks or holds onto the event loop will push the execution of the timeout back. The only guarantee is that the timeout will not execute sooner than the declared timeout interval.

当您设置 setInmediate 时,您正在用大量中间事件填充事件循环,因此您将超时事件推回到队列中。

请记住,事件循环周期在时间上没有相同(精确)的持续时间,因此即使您认为 setInmediate 不应该影响计时器,您也在延长事件循环持续时间。

有趣的文章:

https://nodejs.org/en/docs/guides/timers-in-node/

https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c

编辑:正如您所指出的,在您的情况下恰恰相反,使用 setInmediate 时有更多的迭代。在那种情况下,它可能与事件循环的速度有关,它是动态的,具体取决于程序的负载。