node.js setTimeout分辨率非常低且不稳定

时间:2013-08-19 15:37:28

标签: node.js settimeout resolution

我遇到了setTimeout解析的问题。当我将其设置为50毫秒时,它从51到80毫秒不等。当我使用睡眠模块时,我能够获得50μs的分辨率,那么至少1 ms的setTimeout函数问题是什么?有没有办法解决/避免这种情况?睡眠的问题在于它延迟了所有内容,即使回调函数应该被拍摄,它等待...是否有另一种解决方案来拍摄延迟正好50毫秒的事件?

例如,使用睡眠模块:

var start = new Date().getTime();
sleep.usleep(50);
console.log(new Date().getTime() - start);`

结果是:0。微量时间表示它是51到57μs。那到底是怎么回事?

3 个答案:

答案 0 :(得分:2)

来自setTimeout docs

  

请务必注意,您的回调可能不会在完全延迟的毫秒内被调用

延迟的精确度取决于代码阻塞的程度,这意味着如果您在代码所具有的单个线程上执行大量操作,setTimeout可能会被大量延迟触发。相反,它几乎是准确的。

你可以看到自己的差异,执行这个

var start = Date.now();
setTimeout(function() { console.log(Date.now() - start); }, 500);
for(var i=0; i<999999999; ++i){}

// 1237ms

并注意与此区别:

var start = Date.now();
setTimeout(function() { console.log(Date.now() - start); }, 500);

// 507ms

答案 1 :(得分:0)

因此,为了实现setTimeout之类的最佳时间速率,我们希望尽可能小地保持给定模块的事件循环。这最大限度地减少了V8引擎为循环工作所花费的时间。最佳案例场景:

setInterval(function(){}, 50);

如果这是文件中唯一的东西,那么精度会非常高,因为没有别的东西在进行。所以,我们做的是,我们为特定模块分叉一个进程,该模块仅执行我们想要在此时间间隔内完成的工作。如果函数中唯一的东西是异步请求,它就像上面那样好。因此我们在setInterval函数上获得了非常高的精度。

在一个文件中,我们需要以下内容,我们称之为file1.js。

var http = require('http');

var options = {
    hostname: 'localhost',
    port: 8888,
    path:'/',
    method: 'GET'
}

setInterval(function(){
    console.log('File:' + (new Date).getTime() % 50);
    //The Modulus of the time in MS should change by no more than 1 MS on consecutive runs, I confirmed this works just dandy on my system(though the first couple intervals were slower in some instances, worse I saw was a 3 MS delay)
    var req = http.request(options, function (res) {
        res.on('data', function (data) {
            console.log(data.toString());
        });
    });

    req.end();
}, 50);

在第二个文件中,我们可以做更多的工作,无论我们想要什么工作。重要的是我们生成了一个进程来完成上述工作,包含在其OWN PROCESS中。这允许进程V8处理器保持此事件循环非常小。我们仍然是CPU上给定进程的操作系统管理的受害者,但是我们仍然可以期望我们的file1.js模块至少每毫秒获得一次注意,因为它只是异步调用,然后查找下次需要启动所述异步调用时,我们在调用之间获得的最大延迟是1ms(至少这是我在系统中看到的所有内容)。因此,另一个文件可以包含任意数量的工作,以及一个非常重要的部分:

file2.js:

var http = require('http');
var child_process = require('child_process');


http.createServer(function (req, res) {
    res.write('Hi There');
    res.end();
}).listen(8888);

///Do whatever else you need to do

child_process.fork('file1.js');//Add in this line!!!!

预期产出:

File:29
Hi There
File:29
Hi There
File:30//Notice these values only increase by 0 or 1.  
Hi There
File:31
Hi There
File:31
Hi There
File:32
Hi There
File:34//Uh oh, one went up by 2... not terrible
Hi There
File:35
Hi There
File:35

答案 2 :(得分:0)

是的,我希望它更准确,我的搞笑waitSort可以工作:)

但是它在这里工作但在节点

中没有

&#13;
&#13;
const posInts = [5,2,7,9,4,6,1,3]

const waitSort = arr => new Promise(done => {
  const ret = []
  const last = Math.max(...arr)
  arr.forEach(i => {
    setTimeout(() => {
      ret.push(i)
      if(i === last){
        done(ret)
      }
    }, i)
  })
})

waitSort(posInts).then(console.log)
console.log(posInts)
&#13;
&#13;
&#13;