nextTick vs setZeroTimeout vs setTimeout (v3)

Revision 3 of this benchmark created by stagas on


Preparation HTML

<script>
  // setup
  var iterations = 1000
    , n = iterations
    ;
  
  // nextTick - by stagas / public domain
  var nextTick = (function () {
      var queue = [];
      var dirty = false;
      var fn;
      var hasPostMessage = !!window.postMessage;
      var messageName = 'nexttick';
      var trigger = (function () {
          return hasPostMessage
              ? function trigger () {
                  window.postMessage(messageName, '*');
                }
              : function trigger () {
                  setTimeout(function () { processQueue() }, 0);
                };
      }());
      var processQueue = (function () {
          return hasPostMessage
              ? function processQueue (event) {
                    if (event.source === window && event.data === messageName) {
                        event.stopPropagation();
                        flushQueue();
                    }
                }
              : flushQueue;
      })();
      function flushQueue () {
          while (fn = queue.shift()) {
              fn();
          }
          dirty = false;
      }    
      function nextTick (fn) {
          queue.push(fn);
          if (dirty) return;
          dirty = true;
          trigger();
      }
  
      if (hasPostMessage) 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 WebKit 537.36 / undefined
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