nextTick vs setZeroTimeout vs setTimeout

Benchmark created by stagas on


Preparation HTML

<script>
  // setup
  var iterations = 1000
    , n = iterations
    ;
  
  // nextTick - by stagas / public domain
  var nextTick = (function () {
    var queue = []
      , dirty = false
      , fn
      , hasPostMessage = !!window.postMessage
      , messageName = 'nexttick';
    function flushQueue () {
      while (fn = queue.shift()) {
        fn();
      }
      dirty = false;
    }
    var trigger = (function () {
      return hasPostMessage
        ? function () { window.postMessage(messageName, '*') }
        : function () { setTimeout(function () { processQueue(); }, 0) };
    }());
    var processQueue = (function () {
      return hasPostMessage
        ? function (event) {
            if (event.source === window && event.data === messageName) {
              event.stopPropagation();
              flushQueue();
            }
          }
        : flushQueue;
    })();
    function nextTick (fn) {
      queue.push(fn);
      if (dirty) return;
      dirty = true;
      trigger();
    }
  
    hasPostMessage
      && (nextTick.listener = window.addEventListener('message', processQueue, true));
  
    nextTick.removeListener = function () {
      window.removeEventListener('message', processQueue, true);
    }
  
    return nextTick;
  })();
  
  // setZeroTimeout - L. David Baron <dbaron@dbaron.org>
  var setZeroTimeout = (function() {
    var timeouts = [];
    var messageName = "zero-timeout-message";
  
    // Like setTimeout, but only takes a function argument.  There's
    // no time argument (always zero) and no arguments (you have to
    // use a closure).
    function setZeroTimeout(fn) {
      timeouts.push(fn);
      window.postMessage(messageName, "*");
    }
  
    function handleMessage(event) {
      if (event.source == window && event.data == messageName) {
        event.stopPropagation();
        if (timeouts.length > 0) {
          var fn = timeouts.shift();
          fn();
        }
      }
    }
  
    window.addEventListener("message", handleMessage, true);
  
    setZeroTimeout.removeListener = function () {
      window.removeEventListener('message', handleMessage, true);  
    }
    
    // Add the one thing we want added to the window object.
    return setZeroTimeout;
  })();
</script>

Setup

n = iterations;

Teardown



            nextTick.removeListener();
  setZeroTimeout.removeListener();
        
  

Test runner

Ready to run.

Testing in
TestOps/sec
nextTick
// async test
// nextTick
(function loop (n) {
  if (--n) nextTick(loop)
  else deferred.resolve();
})(n);
ready
setZeroTimeout
// async test
// setZeroTimeout
(function loop (n) {
  if (--n) setZeroTimeout(loop)
  else deferred.resolve();
})(n);
ready
setTimeout
// async test
// setTimeout
(function loop (n) {
  if (--n) setTimeout(loop, 0)
  else deferred.resolve();
})(n);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by stagas on
  • Revision 3: published by stagas on