¿Por qué node.js maneja setTimeout (func, 1.0) incorrectamente?

Mientras trabajaba en un proyecto sensible al tiempo, utilicé el siguiente código para probar la granularidad de los eventos de tiempo disponibles, primero en mi máquina de escritorio en Firefox, luego como código node.js en mi servidor Linux. La ejecución de Firefox produjo resultados predecibles, con un promedio de 200 fps en un tiempo de espera de 1 ms e indicando que tuve eventos de temporización con granularidad de 5 ms.

Ahora sé que si utilizo un valor de tiempo de espera de 0, el motor Chrome V8 Node.js está construido en realidad no delegaría el tiempo de espera a un evento, sino que lo procesaría de inmediato. Como se esperaba, los números promediaron 60,000 fps, procesando claramente constantemente a la capacidad de la CPU (y verificado con la parte superior). Pero con un tiempo de espera de 1 ms, los números todavía estaban alrededor de 3.5-4 mil ciclos () por segundo, lo que significa que Node.js no puede estar respetando el tiempo de espera de 1 ms, lo que crearía un máximo teórico de 1 mil ciclos () por segundo. @

Jugando con un rango de números, obtengo:

2 ms: ~ 100 fps (tiempo de espera verdadero, que indica una granularidad de 10 ms de eventos de temporización en Linux) 1.5: mismo 1.0001: mismo 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

El comportamiento de setTimeout (func, 0) parece excusable, porque la especificación ECMAScript presumiblemente no promete que setTimout delegue la llamada a una interrupción real a nivel del sistema operativo. Pero el resultado para cualquier cosa 0 <x <= 1.0 es claramente ridículo. Di una cantidad explícita de tiempo de retraso, y el tiempo mínimo teórico para n llamadas en x retraso debería ser (n-1) * x. ¿Qué diablos está haciendo V8 / Node.js?

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();

Respuestas a la pregunta(4)

Su respuesta a la pregunta