setTimeoutとかsetIntervalを同時に走らせるときのはなし

var i = 0;
(function loop() {
  console.log(i++);
  setTimeout(function() {
    loop();
    loop();
  }, 0);
})();

このコード動かしてみるとわかるけど、途中で処理がつまってほぼ動かなくなる。node.jsとchromeで同じだった。これloop()は一回で二つ同時に呼んでるので2のn乗で同時に処理されるsetTimeoutが増えていく。前amachangも書いてた気がするけどJSはsetIntervalとかsetTimeoutを同時に処理すると重くなる。上のコードは試しにloop()の呼び出しを一個にすれば普通にさくさく。

どうしてもsetTimeoutの中での再帰複数にして並列で処理したくて、これが原因で使い物にならんくなったので結局こうした。

var q = [];
var _setTimeout = function(fn) {
  q.push(fn);
};

setInterval(function() {
  var fn = q.shift();
  fn && fn();
}, 0);

var i = 0;
(function loop() {
  console.log(i++);
  _setTimeout(function() {
    loop();
    loop();
  });
})();

キューに入れといて一個のタイマーで処理する。実際のコードではちゃんとclearとかの処理もしてるけど。