Measuring Performance in Flash/AS3

by kirupa & friends  |  24 January 2011

  Have questions? Discuss this Flash / ActionScript tutorial with others on the forums.

In programming, there are many ways to write lines of code to return the same result. Of these many ways, some are going to be faster than others. In general, fast is good!

The trick then is to both come up with faster solutions and be able to prove to yourself that a faster solution is indeed faster than something else you have tried. This article isn't going to help you with the first part, but it will certainly try to help you with the second part.

When measuring performance, it is always good to have things to compare against. For this article, let's say you have two ways of squaring a number - Math.pow and xn). What you want to do is figure out which of these approaches is faster:

Let's let the battle begin!

Meet the Stopwatch
Before we pit our two contestants into a bloody battle where only one will walk out alive, we need to figure out what to use to measure performance. In real life, to help measure how fast something is, people tend to use stopwatches. In ActionScript, your stopwatch equivalent is the getTimer function:

var startingTime:Number = getTimer();
 
// have some code here whose running time you are measuring
 
var endingTime:Number = getTimer();
 
trace("Elapsed time: " + endingTime - startingTime);

To be able to use this function, make sure you have the the import flash.utils.getTimer; statement added to the top of your code file.

What this function does is quite simple. The getTimer function returns the number of milliseconds that have elapsed since your application started running. Behind the scenes, the instant your application breathes life, an internal timer starts kicking. All getTimer does is return the value of that internal timer each time you call it.

By calling the getTimer function before and after some code, you can measure how many milliseconds it took to run that code by taking the difference of the two getTimer calls. The smaller the number, the faster your code!

Simple Example
Now that you know what the getTimer function does, let's revisit the initial problem by looking at a small example:

var startingTime:Number = getTimer();
 
for (var i:Number = 0; i < 10000; i++)
{
var xA:Number = Math.random() * 1000;
var xB:Number = Math.random() * 1000;
var yA:Number = Math.random() * 1000;
var yB:Number = Math.random() * 1000;
 
var xDiff:Number = xA - xB;
var yDiff:Number = yA - yB;
 
Math.sqrt(Math.pow(xDiff,2) + Math.pow(yDiff,2));
}
 
var endingTime:Number = getTimer();
 
trace("Elapsed time: " + endingTime - startingTime);

What I want to measure is the performance of calculating the Pythagorean theorem using the Math.pow function first. Because a single call in this case is too fast to measure, I am using a loop to artificially inflate the number of times that our one line gets called. Once you have run this code a few times, your elapsed time in milliseconds should start to fall within a very narrow range.

Next up, we want to change our theorem to use the x2 approach instead and compare the results. When comparing two particular approaches to see which one is faster, try to keep everything as same as possible with the exception of the variation you are measuring.

The x2 approach looks as follows:

var startingTime:Number = getTimer();
 
for (var i:Number = 0; i < 10000; i++)
{
var xA:Number = Math.random() * 1000;
var xB:Number = Math.random() * 1000;
var yA:Number = Math.random() * 1000;
var yB:Number = Math.random() * 1000;
 
var xDiff:Number = xA - xB;
var yDiff:Number = yA - yB;
 
Math.sqrt(xDiff * xDiff + yDiff * yDiff);
}
 
var endingTime:Number = getTimer();
 
trace("Elapsed time: " + endingTime - startingTime);

Notice that almost everything is identical with the exception of the last line in the for loop where we replace Math.pow with x2.

At the end of both experiments, you can get an idea of which approach is faster. As you may have guessed from the very beginning,  x2 is actually faster. Before going further and pursuing any action against Math.pow, read the following section first on how to increase the accuracy of your measurements.

Things to Keep in Mind
The example I used earlier is a quick and dirty way for measuring the performance between two different approaches that return the same result. If you are looking for more accurate performance comparisons or wish to make sweeping generalizations, try to keep the following list in mind.

  1. If you are just measuring the performance of some code (as we are in the squaring example), try to avoid rendering any visuals unless it is critical for your comparison.
  2. While they are both intertwined, avoid using trace statements and avoid using the debug Flash player that you see when you test from within the Flash IDE. The reason is that there are optimizations made to speed things up when your content is viewed at run-time in the browser. Instead of the trace statement, use a simple textfield to output your results so that it is viewable at run-time instead.
  3. For testing simple statements, avoid wrapping them into function calls if possible:
for (var i:Number = 0; i < 10000; i++)
{
var randomA:Number = Math.random() * 1000;
var randomB:Number = Math.random() * 1000;
var randomC:Number = Math.random() * 1000;
var randomD:Number = Math.random() * 1000;
 
//
// Toggle the commenting on the lines below to see which performs faster
//
var distance:Number = GetDistanceSquare(randomA,randomB,randomC,randomD);
//var distance:Number = GetDistanceSquare(randomA,randomB,randomC,randomD);
}
 

There is a non-trivial amount of overhead to do the magic necessary to call a function, and that overhead will add milliseconds to your getTimer call. Inline what you are measuring instead.

  1. When using a loop to measure some code, change the number of iterations you run your loop for. Some memory or performance issues may only be noticeable after a certain number of runs. With that said, keep your iterations reasonable and somewhat representative of how your code may be used.
  2. Never run your test once and consider yourself good to go. Run your tests a few times to get an average. Ideally, the numbers between each test shouldn't vary a whole lot. If they do vary, then you have a problem!
  3. The order and timing between tests matter. If you are running several tests at once, see if changing the order of the tests or whether inserting a pause of a few frames or a few seconds changes the results a whole lot.

Conclusion
Hopefully you found this article on how to measure performance useful. This article was inspired by this thread, and the contents of the "Things to Keep in Mind" section came largely from feedback by Krilnon, rumblesushi, bwhiting, and maskedman.

Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!

Kirupa's signature!




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.