Skip to content

Instantly share code, notes, and snippets.

@wwalser
Created May 17, 2012 11:58
Show Gist options
  • Save wwalser/2718412 to your computer and use it in GitHub Desktop.
Save wwalser/2718412 to your computer and use it in GitHub Desktop.
Cross browser setImmediate speed tests
/**
* Minified https://github.com/NobleJS/setImmediate
*/
(function(a,h){function i(){if(!a.postMessage||a.importScripts)return!1;var b=!0,f=a.onmessage;a.onmessage=function(){b=!1};a.postMessage("","*");a.onmessage=f;return b}function j(b){b.setImmediate=a.msSetImmediate;b.clearImmediate=a.msClearImmediate}function k(b){b.setImmediate=function(){var b=c.addFromSetImmediateArguments(arguments),d=new a.MessageChannel;d.port1.onmessage=function(){c.runIfPresent(b)};d.port2.postMessage(null);return b}}function l(b){function f(b){b.source===a&&("string"===typeof b.data&& b.data.substring(0,d.length)===d)&&(b=b.data.substring(d.length),c.runIfPresent(b))}var d="com.bn.NobleJS.setImmediate"+Math.random();a.addEventListener?a.addEventListener("message",f,!1):a.attachEvent("onmessage",f);b.setImmediate=function(){var b=c.addFromSetImmediateArguments(arguments);a.postMessage(d+b,"*");return b}}function m(b){b.setImmediate=function(){var b=c.addFromSetImmediateArguments(arguments),a=document.createElement("script");a.onreadystatechange=function(){c.runIfPresent(b);a.onreadystatechange= null;a.parentNode.removeChild(a);a=null};document.documentElement.appendChild(a);return b}}function n(b){b.setImmediate=function(){var b=c.addFromSetImmediateArguments(arguments);a.setTimeout(function(){c.runIfPresent(b)},0);return b}}var c=function(){function b(b,a){this.handler=b;this.args=Array.prototype.slice.call(a)}b.prototype.run=function(){"function"===typeof this.handler?this.handler.apply(h,this.args):eval(""+this.handler)};var e=1,d={},g=!1;return{addFromSetImmediateArguments:function(a){var c= a[0],a=Array.prototype.slice.call(a,1),c=new b(c,a),a=e++;d[a]=c;return a},runIfPresent:function(b){if(g)a.setTimeout(function(){c.runIfPresent(b)},0);else{var e=d[b];if(e){g=!0;try{e.run()}finally{delete d[b],g=!1}}}},remove:function(a){delete d[a]}}}();if(!a.setImmediate){var e="function"===typeof Object.getPrototypeOf&&"setTimeout"in Object.getPrototypeOf(a)?Object.getPrototypeOf(a):a;a.msSetImmediate&&a.msClearImmediate?j(e):(a.MessageChannel?k(e):i()?l(e):"document"in a&&"onreadystatechange"in a.document.createElement("script")?m(e):n(e),e.clearImmediate=c.remove)}})(this);
/**
* Did some performance tests using the absolutely awesome cross browser setImmediate
* implementation at https://github.com/NobleJS/setImmediate.
*
* I noticed that in Firefox performance of setImmediate remained steady and consistently
* outperformed the setTimeout(fun, 0) trick. Chrome was a different story with performance initially
* good but quickly diminishing. I found that if don't let Chrome use MessageChannel (the
* implementation it defaults to) it falls back to what Firefox uses and performance stabilizes.
*
* This Gist is test code you can run in developer tools and jsPerf test cases can be found at:
* (message channel, slow) http://jsperf.com/setimmediate-with-message-channel
* (no message channel, fast) http://jsperf.com/setimmediate-without-message-channel
*/
function createContinuation(){
var recurseMethod = Array.prototype.shift.call(arguments),
args = arguments,
count = 0,
continuation = function(){
count++;
recurseMethod.apply(window, args);
}
Array.prototype.unshift.call(args, continuation);
continuation();
return function(){
return count;
}
}
var timeoutCount = createContinuation(setTimeout, 0);
var immediateCount = createContinuation(setImmediate);
setInterval(function(){
console.log('timeout: ' + timeoutCount());
console.log('immediate: ' + immediateCount());
console.log('delta: ' + (immediateCount() - timeoutCount()));
console.log('percentage: ' + (timeoutCount()/immediateCount())*100);
}, 5000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment