Going loopy with JavaScript
JavaScript June 4th, 2007I am in the middle of writing a JavaScript tree that can handle 100s of thousands of nodes in the tree and needed to see if I can optimize the code. Trying to optimize the loop iterations for array objects, I put together a test case to time the efficiency of various different types of loops in JavaScript.
The test
Create an array of 1 million numbers 0 to 1 million, for each of the loop tests, increment a counter then display it at the end of the iterations.
The test covers the following loops:
- ForLoop - standard for loop accessing the length of the array in the iterator
- ForLoopLocalCount - standard for loop, accessing the length of the array stored in a local variable before the iterator
- ForLoopLocalCountAndIterator - standard for loop accessing the count and the iterator from local variables
- ForInLoop - standard For In loop
- ForInLoopLocalItem - standard For In Loop, but declaring the iterator variable locally first.
- WhileLoop - While loop iterator accessing the length at each iteration
- WhileLoopCountFirst - while loop but storing the length of the array in a local variable before the iterator.
var loopTest = {
itemCount : 1000000,
items : [],
initArray : function()
{
for(var x=0; x < this.itemCount; x++)
{
this.items.push(x);
}
console.log(this.items.length);
},
forLoop : function()
{
var total=0;
for(var i=0;i < this.items.length; i++)
{
total ++;
}
console.log(total );
},
forLoopLocalCount : function()
{
var total=0;
var count = this.items.length;
for(var i=0;i < count; i++)
{
total ++;
}
console.log(total );
},
forLoopLocalCountAndIterator : function()
{
var total=0;
var count = this.items.length;
var i = 0;
for(i=0;i < count; i++)
{
total ++;
}
console.log(total );
},
forInLoop : function()
{
var total=0;
for(item in this.items)
{
total ++;
}
console.log(total);
},
forInLoopLocalItem : function()
{
var total=0;
var item = null;
for(item in this.items)
{
total ++;
}
console.log(total);
},
whileLoop : function()
{
var total=0;
var i = 0;
while(i<this.items.length)
{
total ++;
i++;
}
console.log(total );
},
whileLoopCountFirst : function()
{
var total=0;
var i = 0;
var count = this.items.length;
while(i<count)
{
total ++;
i++;
}
console.log(total );
},
runTests : function()
{
this.initArray();
this.forLoop();
this.forLoopLocalCount();
this.forLoopLocalCountAndIterator();
this.forInLoop();
this.forInLoopLocalItem();
this.whileLoop();
this.whileLoopCountFirst();
console.log("Complete.");
}
}
The test was profiled using the firebug profile option and run in Firefox 2.0.0.4 on a Dual Core Pentium 3.2Ghz machine with 3Gb of ram.
Results & Conclusion
The test results are shown in the table to the right. So what can we conclude from the results?
- Don’t use a For In loop. There is a small increase in performance if you allocate the item variable outside of the loop, but it is still up to 31 times slower than using a for or while loop.
- Always ensure that the count (used in the loop exit test) is stored in a temporary variable outside of the iterator i.e. rather than calling array.length in the iterator exit test.
- When local variables are used to store the iterator and count, a for loop performs the same as a while loop. One would assume that the JavaScript.
- In a For loop, declaring the iterator variable outside of the loop actually slows the iteration down! This I did not expect.
August 29th, 2007 at 11:26 pm
I ran your test script with a variation on forLoop that performs as well as forLoopLocalCount() and whileLoopCountFirst():
forLoopShortcut: function() {
var total = 0;
for (var i = this.items.length; –i >= 0; ) {
total++;
}
console.log(total);
}
February 11th, 2008 at 2:23 pm
Try this:
[code]
whileLoopReverseLocalCount : function ()
{
var i = this.items.length;
while (i–)
{
total++;
}
}[/code]