title: node.js: setInterval() skipping calls
body: <p>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.</p>
  
  <p>The benchmark I used is as follows:</p>
  
  <pre><code>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);
  </code></pre>
  
  <p>There is a long timer of one second and a short one that can be adjusted using the variable <code>short</code>, 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.</p>
  
  <p>Here is how it behaves when the short timer is 1 ms:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Many function calls are skipped. Here it is for 10 ms:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Better, but roughly one function call is skipped every second. And for 20 ms:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Finally for 100 ms:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>In this case it skips very few calls (the gap increased to 2 after 33 seconds and to 3 after 108 seconds.</p>
  
  <p>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.</p>
  
  <p>I have found no references for this particular problem. There is this <a href="http://ejohn.org/blog/accuracy-of-javascript-time/" rel="nofollow noreferrer">much cited Ressig post</a> and lots of related JavaScript questions, but most assume that the code runs in a browser and not in node.js.</p>
  
  <p>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 <a href="http://blog.caustik.com/2012/04/08/scaling-node-js-to-100k-concurrent-connections/" rel="nofollow noreferrer">many more clients perfectly</a>; it must be true that <a href="https://stackoverflow.com/questions/6650134/is-setinterval-cpu-intensive">setInterval() is CPU intensive</a> (or I am doing something wrong).</p>
  
  <p>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.</p>
  
  <p>The real question is: can it be done better, either with setInterval() or other timers within node.js? Thanks in advance.</p>