erichynds

Me!

Welcome to my online development portfolio and blog. I'm Eric Hynds, a 23 year old website developer living outside of Boston, Massachusetts, and I'm passionate about developing functional, standard-compliant, and user-friendly websites.

JavaScript Loop Performance: Caching the ‘.length’ Property of an Array

I was reading this article from SitePoint earlier about how inefficient the JavaScript is behind Google’s new Closure library, and saw some interesting discussion about caching an array’s length property before entering a ‘for’ loop. This is what I’m talking about:

// uncached length property
for(var x=0; x < myArray.length; x++){}
 
// cached length property
for(var x=0, len=myArray.length; x < len; x++){}

I saw this tip and didn’t think twice about it; I’ve always been told that caching the length property is indeed faster. I then saw a couple comments saying otherwise:

Anyway, the loop performance is not as big deal as you present. Of course, it’s nicer and more professional to preassign the array length instead of testing it again in every step. But the performance is not such problem. The Javascript basic operations are very fast, making the difference quite unnoticeable. Those two loops performance will differ only in milliseconds for a million-iterations loop in today’s average computer. This means the same loop traversing an array containing a million items will take about 15 ms if the array.length is tested every time, and about 10 ms if the length is preassigned. So, we are talking about saving nanoseconds per a thousand-iterations loop. This makes no sense from the performance point of view.

And:

These are nearly Identical in performance. Even if the loop does nothing, so that the time spent in the loop is all spent incrementing i and checking its value, it is STILL hard to detect the performance difference. And if you do anything of substance in this loop, the time spent checking against someArray.length is dwarfed by the loop body. This is a stupid complaint.

I have always blindly assumed that the performance hit was due to the interpreter calculating the .length value each time it is referenced, but after talking to some javascript folk (#javascript irc.freenode.net), I discovered that .length is actually a stored value. Since JavaScript doesn’t need to re-calculate it on every iteration of the loop, where would the performance hit come from? Anyway, I thought it would be fun to run some benchmarks of my own to see the difference. Below is little script I put together, but please take it as a grain of salt because JavaScript time is not accurate.

var array = [], start, diff;
var results = { nocache:[], cached:[] }
 
// build array to loop over
for(var x=0; x < 1000000; x++){
	array[x] = x;
}
 
// run tests 25 times
for(var x=0; x < 25; x++){
 
	// length not cached
	start = new Date().getTime();
	for(var y=0; y < array.length; y++){}
	results.nocache[x] = new Date().getTime() - start;
 
	// length cached
	start = new Date().getTime();
	for(var y=0, len=array.length; y < len; y++){}
	results.cached[x] = new Date().getTime() - start;
}
 
// output results
document.write( '<p>No cache time: ' + avg(results.nocache) + ' Values: ' + results.nocache.join(',') + '' );
document.write( '<p>Cached time: ' + avg(results.cached) + ' Values: ' + results.cached.join(',') + '</p>' );
 
// logic from http://javascript.about.com/library/blaravg.htm
function avg(arr){
	var av = 0, cnt = 0, e, len = arr.length;
 
	for(var i = 0; i < len; i++){
		e = +arr[i];
		if(!e && arr[i] !== 0 && arr[i] !== '0') e--;
		if (arr[i] == e){ av += e; cnt++; }
	}
 
	return av/cnt;
}

The code first builds an array with 1,000,000 items, records the execution time of looping over the array 25 times using both methods, and then figures the average. Here are the results:

The results are what I expected except in the Windows versions of Firefox 3.5.2/3.5.5. In all other browsers I tested it is faster to cache the .length value, but in FF3.5 for Windows it is actually faster not to cache. Internet Explorer receives the most benefit with a ~30% increase in performance when caching, with Opera (Linx) and Chrome (Linux) in fourth and fifth place respectively. The amount of time is indeed negligible, but every millisecond counts, right?

If nothing else it is interesting to see how long it takes different browsers to loop through a large array. Firefox and Safari FTW!

Related posts:

  1. jQuery and Performance: What is ‘this’?

Leave a Comment