Search code examples
node.jstimersettimeout

setTimeout is precise on Linux but not on Windows?


I have a simple setTimeout usage:

var oldDate = new Date().getTime();

setInterval(function(){
    var newDate = new Date().getTime();

    console.log(newDate - oldDate, 'ms');

    oldDate = newDate;
}, 7);

This prints on a Linux system with Node(v10.15.2):

8 'ms'
6 'ms'
8 'ms'
7 'ms'
8 'ms'
8 'ms'

But on a Windows system with Node(v10.15.1):

21 'ms'
22 'ms'
20 'ms'
20 'ms'
17 'ms'
23 'ms'
18 'ms'
20 'ms'
22 'ms'
17 'ms'
17 'ms'
22 'ms'
19 'ms'
20 'ms'
23 'ms'
19 'ms'
30 'ms'

It is an absolute mess and runs very randomly.

I need a precise and non-blocking timer. In linux it works like a charm, but I'm curious, why is it so bad in windows?

Thanks!


Solution

  • You can't use the timer subsystem for precise timing.

    It's important to understand that even on Linux, it will only be "precise" provided your Node.js instance's main thread is never busy doing something else, like handling I/O completions or running some of your JavaScript logic. There's only one main thread in a Node.js program (you can have others via Worker), which handles I/O completion callbacks and anything else your code does (unless it's on a worker thread). setTimeout/setInterval schedule normal tasks in the task queue, which also holds other tasks (such as, again, I/O completions).

    If you really need timing that precise, you'll probably need to at least move it to a worker thread, and even then it may not be precise. If not, you might get closer with setImmediate loops. If that isn't close enough, you may need to busy-wait in the worker (which will peg a CPU core, but at least not the main thread).