I 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:

  1. ForLoop - standard for loop accessing the length of the array in the iterator
  2. ForLoopLocalCount - standard for loop, accessing the length of the array stored in a local variable before the iterator
  3. ForLoopLocalCountAndIterator - standard for loop accessing the count and the iterator from local variables
  4. ForInLoop - standard For In loop
  5. ForInLoopLocalItem - standard For In Loop, but declaring the iterator variable locally first.
  6. WhileLoop - While loop iterator accessing the length at each iteration
  7. 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.