requestAnimationFrame-vs-setImmediate Polyfills (v2)

Revision 2 of this benchmark created by Jason Miller on


Description

Test out common requestAnimationFrame pollyfill VS setImmediate for the use-case of deferring execution of a function by the shortest amount of time possible.

Preparation HTML

<script>
// generic rAF polyfill
var rAF = window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          function(fn){ setTimeout(fn, 10); };


// naive implementation
var setImmediate = window.setImmediate ||
  function(fn) {
    var img = new Image();
    img.onerror = fn;
    img.src = '';
  };


// choose-best implementation
var setImmediatePenultimate = (function(f, q, p, reg) {
    q = [];
    f = document.createElement('iframe');
    f.style.cssText = 'position:absolute;top:-999em;left:0;width:1px;height:1px;';
    document.body.appendChild(f);
    function done() {
        for (var i=0; i<q.length; i++) q[i]();
        q.length = 0;
    }
    p = [
        function(fn){
            var w = f.contentWindow;
            w.onmessage = fn;
            w.postMessage('', '*');
        },
        function(fn){
            var img = new Image();
            img.onerror = fn;
            img.src = '';
        },
        function(fn){ setTimeout(fn, 0); }
    ];
    reg = function pick() {
        p.forEach(function(o) {
            try {
                o(function() {
                    if (reg===pick) reg=o, done();
                });
            }catch(e){}
        });
    };
    return function(fn) {
        if (q.push(fn)===1) reg(done);
    };
}());



// make sure the given defer impl is async
function ensureAsync(name, fn, async) {
  fn(function() {
    async = true;
  });
  async = false;
  setTimeout(function() {
    if (async===false) {
      throw new Error(name+'is not asynchronous.');
    }
  }, 100);
}


ensureAsync('requestAnimationFrame', rAF);
ensureAsync('setImmediate', setImmediate);
ensureAsync('setTimeout(0)', function(fn){ setTimeout(fn,0); });
ensureAsync('setImmediatePenultimate', setImmediatePenultimate);
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
requestAnimationFrame
// async test
rAF(function() {
  deferred.resolve();
});
ready
setImmediate
// async test
setImmediate(function() {
  deferred.resolve();
});
ready
setImmediatePenultimate
// async test
setImmediatePenultimate(function() {
  deferred.resolve();
});
ready
setTimeout(0)
// async test
setTimeout(function() {
  deferred.resolve();
}, 0);
ready

Revisions

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

  • Revision 1: published by Jason Miller on
  • Revision 2: published by Jason Miller on