In firefox there seems to be a big performance difference between the following two functions:
var n1 = 12;
var add1 = function(n2){
return n1 + n2;
}
var add2 = (function(){
return function(n2){
return n1 + n2;
}
})();
I thought this must be down to the introduction of another level of scope, so created a third example with the variable cached one level up. But this shows an even greater reduction (80%!)
var add3 = (function(){
var cn1 = n1;
return function(n2){
return cn1 + n2;
}
})();
I would have thought that the closure here would close the performance gap, not enlarge it. Does anybody have an idea what is going on here?
jsPerf test page: http://jsperf.com/variable-scope-speed
Its interesting, but my little testing here seems to confirm my earlier assumption, that is, the jsPerf environment influences scopes and scope-chain look-ups itself. I didn't digg into the "how" and "why", but this is my little testscript:
var n1 = 12;
var add1 = function(n2){
return n1 + n2;
}
var add2 = (function(){
return function(n2){
return n1 + n2;
}
})();
var add3 = (function(){
var cn1 = n1;
return function(n2){
return cn1 + n2;
}
})();
var add4 = function( n2, n1 ) {
return n2 + n1;
}.bind(null, n1);
var tests = [add1, add2, add3, add4],
start, stop, loops;
tests.forEach(function( fnc ) {
loops = 100000;
start = Date.now();
while( loops-- ) {
fnc( 2 );
}
stop = Date.now();
console.info('Method ', fnc.name || fnc.toString(), ': ', stop - start, ' ms.');
});
And the results on my FireFox 14 look like so:
Method add1: 570ms.
Method add2: 566ms.
Method add3: 414ms.
Method add4: 479ms.
Latest Chrome results:
Method add1: 199ms.
Method add2: 136ms.
Method add3: 85ms.
Method add4: 144ms.
Which definately looks more reasonable. A closured scope-chain lookup has to be always faster, simply for the fact that there is a shorter lookup-chain. Even if all modern browsers don't normally do a classic scope chain lookup, I'm aware of that. Anyway, since browsers create pretty clever lookup tables for free (or out-of-scope) variables, all results should at least be the same. It doesn't make any sense to over-optimize the global object access IMO.
As you noticed, I created one additional test-case for a bound method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With