I’ve been doing a lot of work in Node JS recently, and it’s emphasis asynchronous modules has me relying on applying the bind function on closures to wrap asynchronous calls within loops (to preserve the values of variables at function call).
This got me thinking. When you bind variables to a function, you add passed values to that function’s local scope. So in Node (or any JS code that refers to out of scope variables often), is it advantageous to bind out of scope variables (such as modules) to functions so that when used they are part of the local scope?
Example in plain JS:
var a = 1,
func1 = function(b) { console.log(a,b); },
func2 = (function(a,b) { console.log(a,b); }).bind(null, a);
//func1(2) vs func2(2)
Example in Node
var fs = require('fs'),
func1 = function(f) { fs.stat(f, function(err, stats){}); },
func2 = (function(fs, f) { fs.stat(f, function(err, stats){}); }).bind(null, fs);
//func1('file.txt') vs func2('file.txt')
In my above examples, will func1 or func2 be noticeably faster than the other (not including outside factors such as how long it takes to get file stats)?
Here’s a little JSFiddle I threw together that does a quick and dirty benchmark: http://jsfiddle.net/AExvz/
- Google Chrome 14.0.797.0 dev-m
- Func1: 2-4ms
- Func2: 30-46ms
- Google Chrome 14.0.800.0 canary
- Func1: 2-7ms
- Func2: 35-39ms
- Firefox 5.0
- Func1: 0-1ms
- Func2: 35-42ms
- Opera 11.11 Build 2109
- Func1: 21-32ms
- Func2: 68-73ms
- Safari 5.05 (7533.21.1)
- Func1: 23-34ms
- Func2: 71-78ms
- Internet Explorer 9.0.8112.16421
- Func1: 10-17ms
- Func2: 14-17ms
- Node 0.4.8 REPL
- Func1: 10ms
- Func2: 156ms @ 10x more iterations (~15.6ms if both tested with 100000 iterations)
Note: Node’s REPL test is unreliable because it must employ some sort of caching system. After a single benchmark of func1, func2 returned 0ms.
Feel free to contribute your results of a better benchmark.
Generally the effect of reducing scope lookups should be positive. However, the difference is probably rather miniscule on today’s fast JS engines.
In some math-intensive code running on an older JS engine, I used to get some more perf by doing things like this:
So basically bringing functions from outside the function to inside the function’s own scope can have a positive effect, but to be sure you probably should profile the code to be sure.