This is a list of guidelines to make your Javascript faster, often associated with jsPerf benchmarks.
If you have an existing codebase, don't get carried away with premature optimizations. Profile to find the slow bits and pick the low hanging fruit.
Some of the latter lessons in Code School's Chrome DevTools course will teach you how to profile your code.
Seen nested functions like this before?
function doSomething(arg1, arg2) {
function nestedHelper(arg) {
return process(arg);
}
return nestedHelper(arg1) + nestedHelper(arg2);
}
Unfortunately, every time you run the doSomething
function, it recreates the nestedHelper
function. Instead, you should do this:
var iife = (function() {
function privateHelper(arg) {
var result = process(arg);
return result;
}
return function(arg1, arg2) {
return privateHelper(arg1) + privateHelper(arg2);
}
})();
In this case, privateHelper
is created only once.
Benchmark: http://jsperf.com/iifes-vs-nested-functions/2
As with above, using arguments
makes your function variadic, which Javascript engines can't do much about.
Benchmark: http://jsperf.com/how-slow-is-arguments/2
However, don't think that an array parameter is any better (i.e. function(arrayParameter) { ... }
). Between iterating arguments
vs. an array parameter, arguments
is faster.
Benchmark: http://jsperf.com/arguments-vs-array-argument/2
If V8 sees that your function is short, it's more likely to be inlined. So don't fear splitting a large function into many smaller functions.
Evidence of optimizations in V8 can be seen by running this benchmark (notice the variation in IIFE running performance).
Link: http://wingolog.org/archives/2011/06/10/v8-is-faster-than-gcc
You should be aware that comments inside your function increase the likelihood it won't get inlined. Strange, but true! I suppose that is the fate of super-optimized VMs.
However, this shouldn't be a problem at all if you minify your code, right? :-)
Link: http://floitsch.blogspot.com.au/2012/03/optimizing-for-v8-inlining.html
It's much faster to create a variable in the outer scope rather than using Function.bind.
// bind - don't do this
function thisFunction() {
return this.member;
}
var boundFunction = someFunction.bind(this);
// that - do this!
var that = object;
function thatFunction() {
return that.member;
}
Benchmark: http://jsperf.com/bind-vs-that/3
TODO
function Point(x, y) {
this.x = x;
this.y = y;
}
var p1 = new Point(11, 22);
var p2 = new Point(33, 44);
// At this point, p1 and p2 have a shared hidden class
p2.z = 55;
// warning! p1 and p2 now have different hidden classes!
http://www.html5rocks.com/en/tutorials/speed/v8/
TODO
Source: http://www.html5rocks.com/en/tutorials/speed/v8/
TODO
function add(x, y) {
return x + y;
}
add(1, 2); // + in add is monomorphic
add("a", "b"); // + in add becomes polymorphic
Source: http://www.html5rocks.com/en/tutorials/speed/v8/
TODO
var o = { x: 1 };
delete o.x; // true
o.x; // undefined
http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
TODO
- http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
- http://ejohn.org/blog/dom-documentfragments/
TODO: give example of moving processing to another thread
TODO: Shims?
TODO
Below are some of the other experiments I performed. They weren't included in the above list because the wins are fairly marginal.
- Return only at endpoints of a function: http://jsperf.com/early-return-or-not
- Writing an int32 typed array is marginally quicker in V8: http://jsperf.com/uint32array-write-performance
- Reading an int32 typed array vs. a normal array doesn't make a difference: http://jsperf.com/uint32array-read-performance