node.js:setInterval() 跳过调用 [英] node.js: setInterval() skipping calls

查看:77
本文介绍了node.js:setInterval() 跳过调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于即将到来的 node.js 项目,我需要定期执行各种内务管理任务.具体来说,有些任务每毫秒执行一次,有些每 20 毫秒执行一次(每秒 50 次),还有一些每秒执行一次.所以我考虑使用 setInterval(),结果很有趣:很多函数调用都被跳过了.

For an upcoming project with node.js I need to perform various housekeeping tasks at periodic times. Specifically some tasks every millisecond, others every 20 ms (50 times per second) and still others every second. So I thought about using setInterval(), with funny results: many function calls were being skipped.

我使用的基准如下:

var counter = 0;
var seconds = 0;
var short = 1;
setInterval(function() {
        counter ++;
    }, short);
setInterval(function() {
        seconds ++;
        log('Seconds: ' + seconds + ', counter: ' +
             counter + ', missed ' +
             (seconds * 1000 / short - counter));
    }, 1000);

有一个一秒的长计时器和一个短计时器,可以使用变量 short 进行调整,在本例中为 1 毫秒.每一秒我们都会打印出短周期中预期的滴答数与短计数器的实际更新次数之间的差值.

There is a long timer of one second and a short one that can be adjusted using the variable short, in this case 1 ms. Every second we print the difference between the number of expected ticks in the short cycle and the actual number of times the short counter was updated.

以下是短定时器为 1 ms 时的行为:

Here is how it behaves when the short timer is 1 ms:

2012-09-14T23:03:32.780Z Seconds: 1, counter: 869, missed 131
2012-09-14T23:03:33.780Z Seconds: 2, counter: 1803, missed 197
2012-09-14T23:03:34.781Z Seconds: 3, counter: 2736, missed 264
...
2012-09-14T23:03:41.783Z Seconds: 10, counter: 9267, missed 733

许多函数调用被跳过.这是 10 毫秒:

Many function calls are skipped. Here it is for 10 ms:

2012-09-14T23:01:56.363Z Seconds: 1, counter: 93, missed 7
2012-09-14T23:01:57.363Z Seconds: 2, counter: 192, missed 8
2012-09-14T23:01:58.364Z Seconds: 3, counter: 291, missed 9
...
2012-09-14T23:02:05.364Z Seconds: 10, counter: 986, missed 14

更好,但大约每秒跳过一个函数调用.并持续 20 毫秒:

Better, but roughly one function call is skipped every second. And for 20 ms:

2012-09-14T23:07:18.713Z Seconds: 1, counter: 46, missed 4
2012-09-14T23:07:19.713Z Seconds: 2, counter: 96, missed 4
2012-09-14T23:07:20.712Z Seconds: 3, counter: 146, missed 4
...
2012-09-14T23:07:27.714Z Seconds: 10, counter: 495, missed 5

最后 100 毫秒:

2012-09-14T23:04:25.804Z Seconds: 1, counter: 9, missed 1
2012-09-14T23:04:26.803Z Seconds: 2, counter: 19, missed 1
2012-09-14T23:04:27.804Z Seconds: 3, counter: 29, missed 1
...
2012-09-14T23:04:34.805Z Seconds: 10, counter: 99, missed 1

在这种情况下,它跳过很少的调用(间隔在 33 秒后增加到 2,在 108 秒后增加到 3.

In this case it skips very few calls (the gap increased to 2 after 33 seconds and to 3 after 108 seconds.

数字各不相同,但在运行之间惊人地一致:在 9267、9259 和 9253 运行 10 秒后,运行第一个 1 毫秒基准测试 3 次会产生延迟.

The numbers vary, but are surprisingly consistent between runs: Running the first 1 ms benchmark three times yielded a delay after 10 seconds of 9267, 9259 and 9253.

我没有找到针对此特定问题的参考资料.有这个 经常引用的 Ressig 帖子 和许多相关的 JavaScript 问题,但是大多数人认为代码在浏览器中运行,而不是在 node.js 中运行.

I have found no references for this particular problem. There is this much cited Ressig post and lots of related JavaScript questions, but most assume that the code runs in a browser and not in node.js.

现在问一个可怕的问题:这里发生了什么?开个玩笑;显然函数调用被跳过.但我看不到这种模式.我认为长周期可能会阻止短周期,但在 1 毫秒的情况下没有任何意义.短周期函数调用不会重叠,因为它们只是更新一个变量,即使是 1 毫秒的短周期,node.js 进程也接近 5% 的 CPU.不过,平均负载很高,约为 0.50.我不知道为什么一千个调用对我的系统造成如此大的压力,因为 node.js 处理 更多客户端完美;setInterval() 是 CPU 密集型的(或者我做错了什么),这一定是真的.

Now for the dreaded question: what is going on here? Just joking; obviously function calls are being skipped. But I fail to see the pattern. I thought that the long cycles might be preventing the short ones, but it doesn't make any sense in the 1 ms case. Short cycle function calls are not overlapping since they just update a variable, and the node.js process is near 5% CPU even with a short cycle of 1 ms. Load average is high though, at about 0.50. I don't know why a thousand calls are stressing my system so much, though, since node.js handles many more clients perfectly; it must be true that setInterval() is CPU intensive (or I am doing something wrong).

一个明显的解决方案是使用更长的计时器对函数调用进行分组,然后多次运行短周期函数调用来模拟更短的计时器.然后将长周期用作扫帚马车",使任何在较低间隔中错过的电话.示例:设置 20 毫秒和 1000 毫秒的 setInterval() 调用.对于 1 ms 调用:在 20 ms 回调中调用它们 20 次.对于 1000 ms 调用:检查 20ms 函数被调用了多少次(例如 47),执行任何剩余的调用(例如 3).但是这个方案会有点复杂,因为调用可能会以有趣的方式重叠;虽然它看起来像,但它也不会是常规的.

An obvious solution is to group function calls using longer timers, and then run short cycle function calls many times to simulate a shorter timer. Then use the long cycle as a "broom wagon" that makes any calls missed in the lower intervals. An example: set up 20 ms and 1000 ms setInterval() calls. For 1 ms calls: call them 20 times in the 20 ms callback. For the 1000 ms call: check how many times the 20ms function has been called (e.g. 47), do any remaining calls (e.g. 3). But this scheme is going to be a bit complex, since calls may overlap in interesting ways; also it will not be regular although it may look like it.

真正的问题是:使用 setInterval() 或 node.js 中的其他计时器可以做得更好吗?提前致谢.

The real question is: can it be done better, either with setInterval() or other timers within node.js? Thanks in advance.

推荐答案

javascript 中的 SetInterval 函数不准确.您应该尝试使用高分辨率计时器.在 javascript 中构建准确的计时器

SetInterval functions in javascript are not accurate. You should try to use a high resolution timer.Building accurate Timers in javascript

这篇关于node.js:setInterval() 跳过调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆