ActionScript 3.0: Screaming fast for loops

In the last post, I wrote about what I think is a better structure for while loops. Today, it’s all about for loops and demonstrating how the little things can go a long way in improving loop performance in your applications.

I was intrigued by Nick Bylik’s blog post about optimizing ActionScript and decided to take his testing a bit further. The results were dramatic. At the end of this article is a link to the fla files (CS4 and CS5) I used for testing. The idea is simple: you select which loop to run and click the start button. The appropriate loop is then executed and the results are displayed in a textbox when it has completed. Each loop completes the same task: summing a collection of ten million numbers.

Below is the code and an explanation for each loop so that you can see how they differ if you don't feel up to downloading the fla files. I also included the average time the loops took to complete on my machine. The results show that an optimized loop is capable of running up to 15x more quickly than a standard loop on even the simplest of operations!

A Standard For Loop

for(var i:int = 0; i < myArray.length; i++)
{
    result += myArray[i];
}

Avg Time: 1400 milliseconds (1.4 seconds)
The first and by far the slowest loop of the lot is the standard for loop. This is a pretty typical loop structure, but as you can see from testing, the performance is awful. There are a couple of reasons for this; first, we are looking up the length of the array every iteration of the loop to compare it against the value of i, our increment counter. Second, we are forcing the program to do a lot of casting on myArray[i] to finally get it converted to a Number.

To us, it may look like a simple operation: result += myArray[i], but as Nick points out in his blog, what is actually happening is all this:

result += Number(Object(myArray[i]).toString());  

That is a ton of work we’re asking the program to do every single iteration of the loop. First, it must fetch the value at myArray[i], which it casts to an Object which then gets converted to a string which is subsequently cast to a Number. This is not exactly ideal if we’re after performance.

A For Each Loop

for each(var i:Number in myArray)
{
	result += i;
}

Avg Time: 207 milliseconds (0.2 seconds)
The for each loop helps considerably, especially with regards to casting because we’re telling the program which data type the objects are. This nets you a big performance gain - about 7x to 10x faster than the standard loop we used above! However, we can even improve upon this; let’s see how.

An Optimized For Loop

var limit:int = myArray.length;
for(var i:int = 0; i < limit; i++)
{
	result += Number(myArray[i]);
	++i;
	result += Number(myArray[i]);
}

Avg Time: 145 milliseconds (0.1 seconds)
This loop is melt your face off fast! It can be as much as 15x faster than the standard for loop! But why? Well, let’s look at the optimizations that were made. First, unlike in the standard loop, we precalculated the limit so we’re not looking up the length of the array every iteration any more. We’re also taking care of the casting ourselves so there are not a lot of nasty conversions going on behind the scenes. Lastly, we “unrolled” the loop a bit by taking care of two operations every iteration; this halves the number of times we’ll need to go through the loop. A shout-out here to my buddy, Paul Cummins, for that tip!

An Optimized For Loop on a Vector Object

var limit:int = myVec.length;
for(var i:int = 0; i < limit; i++)
{
	result += myVec[i];
	++i;
	result += myVec[i];
}

Avg Time: 271 milliseconds (0.27 seconds)
The last loop I threw in was for a Vector instead of a standard array. In theory Vectors are supposed to be faster because they’re a typed collection which means no conversions. Great! But does it hold up in practice? Well, it's certainly better than the standard for loop, but for the most part it performs roughly the same as the for each loop on the standard array.

A Final Note
The results of my tests were the same across the following platforms:
- Published directly from the Flash IDE (all loops ran more slowly here)
- As a standalone executable
- In the following browsers: Firefox, Chrome, IE, Safari, Opera (IE performed the slowest)
- Browsers using the incubator build of Flash Player 11 ran the loops faster than when using the 10.3 version

When running the swf directly with the Flash Player, the Vectorized loop was the fastest, followed by the for each loop, then the optimized for loop and lastly the standard loop. However, this is generally not how Flash content is viewed. For that reason I chose a more "real world" example and ran the tests in an HTML file with Google Chrome and Flash Player version 10.3.

Hopefully this post was helpful to you, or at least informative. These techniques may seem like small things, but as shown, they can add up to give you HUGE performance gains!

In the near future I plan on testing these out on mobile platforms as well. Once I do, I will be sure to post the results!

Grab the .fla files (CS4 & CS5)

Bookmark and Share

Leave a Reply

Subscribe to RSS feed FGS5 Badge