Javascript prototype functions and performance

Written by Ryan on September 2nd, 2011

Apparently I decided to spend my Friday night profiling javascript and I figured I might as well share a couple performance differences I discovered where I wasn’t expecting them.

First off, it’s apparently faster to instantiate objects by extending their prototype than it is to put their methods inside the function’s brackets. I got this idea from this stackoverflow question and am going to show a variation of the test proposed by Andrew:

var X,Y, x,y,z, i, intNow;

X = function() {};
X.prototype.message = function(s) { var mymessage = s + "";}
X.prototype.addition = function(i,j) { return (i *2 + j * 2) / 2; }

Y = function() {
    this.message = function(s) { var mymessage = s + "";}
    this.addition = function(i,j) { return (i *2 + j * 2) / 2; }
};

function Z() {
    this.message = function(s) { var mymessage = s + "";}
    this.addition = function(i,j) { return (i *2 + j * 2) / 2; }
};

intNow = (new Date()).getTime();
for (i = 0; i < 1000000; i++) {
    x = new X();
}
console.log((new Date()).getTime() - intNow); 
// Chrome=1089ms; IE9=1494ms; FF=1842ms; Safari=414ms

intNow = (new Date()).getTime();
for (i = 0; i < 1000000; i++) {
    y = new Y();
}
console.log((new Date()).getTime() - intNow); 
// Chrome=1270ms; IE9=1721ms; FF=2266ms; Safari=896ms

intNow = (new Date()).getTime();
for (i = 0; i < 1000000; i++) {
    z = new Z();
}
console.log((new Date()).getTime() - intNow); 
// Chrome=1292ms; IE9=1713ms; FF=2257ms; Safari=885ms

You can see from the times after the console logs that using .prototype is faster across the board. It's not even really close in some browsers. I've always liked putting object functions inside the objects' brackets because I think it improves readability but the results are pretty clear - you pay a solid performance penalty for that organization.

Also, unrelatedly, Safari smokes everybody at this test.

That made me curious about whether or not it would also be faster to call functions assigned to an object's prototype than it would be to call the same function declared globally. I modified the previous test and ran:

var i, intNow;

function test() {
	return this + '-test';
};

String.prototype.test = function() {
	return this + '-test';
};
var t = 'test';

intNow = (new Date()).getTime();
for (i = 0; i < 1000000; i++) {
    test(t);
}

console.log((new Date()).getTime() - intNow); 
// Chrome=2504ms; IE9=2160ms; FF=5623ms; Safari=944ms

intNow = (new Date()).getTime();
for (i = 0; i < 1000000; i++) {
    t.test();
}

console.log((new Date()).getTime() - intNow); 
// Chrome=2329ms; IE9=1286ms; FF=1955ms; Safari=486ms

It appears to be consistently faster to attach a function to an object and call it than it is to call the function globally. Does that mean you should always attach functions to objects? Perhaps. I think there's a fair scope related argument for doing that anyway but the performance benefit was a lot higher than I expected.

Now if you'll excuse me, I need to go change some code on SourceAudio. Apparently I've been doing this all wrong.

Note: Don't judge Chrome vs the other browsers in these tests. It's my workhorse browser and I've got seven tabs open while the others were all fresh boots.

 

Leave a Comment