在处理对时间敏感的项目时,我使用下面的代码测试可用的定时事件的粒度,首先在Firefox的台式机上,然后在Linux服务器上作为node.js代码进行测试。 Firefox运行产生了可预见的结果,在1毫秒的超时时间内平均为200 fps,表明我有5毫秒粒度的计时事件。

现在我知道,如果我将超时值设为0,则基于Chrome V8引擎Node.js的构建实际上不会将超时委托(delegate)给事件,而是会立即对其进行处理。正如预期的那样,这些数字平均为60,000 fps,显然以CPU容量不断进行处理(并通过top进行验证)。但是当超时时间为1毫秒时,该数字仍约为每秒3.5-4千个cycle(),这意味着Node.js可能无法遵守1毫秒的超时,这将导致理论上的最大值为每秒1000周期()。

玩一系列数字,我得到:

  • 2ms:〜100 fps(真实超时,指示Linux上定时事件的粒度为10ms)
  • 1.5:相同
  • 1.0001:相同
  • 1.0:3,500-4,500 fps
  • 0.99:2,800-3,600 fps
  • 0.5:1,100-2,800 fps
  • 0.0001:1,800-3,300 fps
  • 0.0:〜60,000 fps

  • setTimeout(func,0)的行为似乎是可原谅的,因为ECMAScript规范可能无法保证setTimout将调用委派给实际的OS级中断。但是任何0
    var timer, counter = 0, time = new Date().getTime();
    
    function cycle() {
        counter++;
        var curT = new Date().getTime();
        if(curT - time > 1000) {
            console.log(counter+" fps");
            time += 1000;
            counter = 0;
        }
        timer = setTimeout(cycle, 1);
    }
    
    function stop() {
        clearTimeout(timer);
    }
    
    setTimeout(stop, 10000);
    cycle();
    

    最佳答案

    为了完整起见,我想指出nodeJS的实现:

    https://github.com/nodejs/node-v0.x-archive/blob/master/lib/timers.js#L214

    这是:

    // Timeout values > TIMEOUT_MAX are set to 1.
    var TIMEOUT_MAX = 2147483647; // 2^31-1
    ...
    exports.setTimeout = function(callback, after) {
        var timer;
    
        after *= 1; // coalesce to number or NaN
    
        if (!(after >= 1 && after <= TIMEOUT_MAX)) {
            after = 1; // schedule on next tick, follows browser behaviour
        }
    
        timer = new Timeout(after);
        ...
    }
    

    请记住以下声明:



    然后我们在此处传递same timeout value (1)
    Timer的实现在这里:
    https://github.com/nodejs/node-v0.x-archive/blob/master/src/timer_wrap.cc

    关于node.js - 为什么node.js无法正确处理setTimeout(func,1.0)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9288050/

    10-15 14:50