Sho just posted a really interested article on why he won't be using the int data type very frequently in ActionScript 3. Up until reading it, I had believed that as in other languages, there were large performance benefits to using ints and uints appropriately in AS3. Turns out that isn't the case.
I did some quick testing on this, which confirm Sho's assertion that int is only slightly faster than Number in ideal circumstances, but the results from uint were much more surprising.
I did a simple test that ran through 16777215 iterations of a for loop, using int, Number, and uint types as the iterator variable. It did 50 passes, and calculated an average time per pass. This should be ideal conditions for using ints and uints. The results were really interesting:
int: 24-26ms
Number: 31-36ms
uint: 105-225ms
So as Sho said, int is not much faster than Number, but it probably still makes sense for use as an iterator and in other obvious cases. But uint is ridiculously slow, and very erratic! The other types were very consistent when I ran this test multiple times (remember the results were from 50 averaged passes, and so should be consistent), but uint was all over the place. Some of the individual passes went as high as 500ms, and as low as 65ms.
My takeaway without more research: Avoid uint, unless you have a really good reason for forcing the type. Use ints where they make sense, but don't agonize over the performance implications of int versus Number. Default to Number whenever you aren't sure. Most importantly, don't take things for granted - test and benchmark wherever you can - you might be surprised by the results!
It's important to note that typing in general does result in huge speed benefits in AS3. Running the above test with an untyped iterator averages 380-430ms per pass (I even had to reduce the number of passes to 20 to avoid a 15 second timeout). It also has a lot of secondary benefits like compile and run-time type checking.
A huge thank you to Sho for posting about this - I'm glad I didn't spend months or years of coding carefully choosing the best numeric type, thinking I was optimizing my code, when in fact I was gaining very little performance (or in the case of uint, actually harming performance).
Update
I've done a few more tests, as per Sho's suggestion, and thought I'd post the results (they are pretty close to what you'd expect based on Sho's post). I used the same methodology as above, but inserted a small formula that was run each iteration. Here are the results:
Assignment ( var a:TYPE = 0; )
int: 24-45ms
Number: 24-36ms
uint: 25-37ms
Statistically, they look the same, which is to be expected.
Assignment ( var a:TYPE = 0.5; )
int: 56-83ms
Number: 26-43ms
uint: 57-92ms
Predictably, Number is faster for fractional assignments, as the value does not need to be converted to an integer.
Division ( var a:TYPE = i/2; )
int: 60-105ms
Number: 34-64ms
uint: 184-278ms
Number is a much faster type for division, as expected from Sho's post. uint trails badly.
Multiplication ( var a:TYPE = i*2; )
int: 78-129ms
Number: 39-64ms
uint: 207-280ms
Similar results to division. I thought int might perform better as the value would never have to be converted to a float (whereas in division it would).
Addition ( var a:TYPE = i+2; )
int: 31-49ms
Number: 44-55ms
uint: 85-113ms
As expected from the plain iterator test, int is slightly faster for integer addition.
Bitshift ( var a:TYPE = i<<1; )
int: 31-63ms
Number: 61-114ms
uint: 71-130ms
int outperforms Number fairly handily in bit operations, this is likely because Number needs to be converted into an int to have bit operators applied. This is the only test so far that uint does passably well in (other than assignment).
Comments (16)
Thanks, Grant. Very interesting. Try doing math inside your loop with both ints and Numbers. To me, it looks like addition is still faster with ints, but division is faster with Numbers. So you should test the timings based on the code you actually write to see if Numbers are faster or ints.
Posted by: Sho at June 15, 2006 01:00 PMURL: http://kuwamoto.org
Sho - yes, I'm planning to test a number of different scenarios, but wanted to start with a very common one that should favour int/uint.
Posted by: Grant Skinner at June 15, 2006 01:13 PMURL: http://gskinner.com/
You know, Adobe should really stress the information presented in your and Sho's blogs, because users coming from another language will certainly bang their heads on this!
Posted by: Mike K at June 15, 2006 03:47 PMURL:
Thanks detailed benchmarks. Does that mean there are a lot of areas in Bitmap manipulation that can gain advantages for finding ways to use int over uint?
Basically a test showing the performance of the different readByte types of a ByteArray might be interesting.
Just a couple of thoughts.
Posted by: Renaun at June 15, 2006 03:59 PMURL: http://renaun.com
Thanks for the great info, Grant. Could you tell us a little about the system you performed these timings on?
Posted by: Darrin Massena at June 15, 2006 11:32 PMURL:
One other thing worth trying inside your loops is array indexing. Even though Array lookup is theoretically the same operation as any other dynamic property lookup, the AVM team did some work to optimize the common case with arrays...i.e., building and using tightly packed arrays. So it would be worth seeing if using an int vs. Number as your indexer makes a difference.
Posted by: Ely at June 15, 2006 11:54 PMURL: http://www.quietlyscheming.com
Darrin:
Have a look at the 2 previous posts where Grant goes on about his experiences with his new macbook. There is all kinds of information about the machine he did the tests on.
Posted by: Lanny at June 16, 2006 09:05 AMURL: http://gskinner.com
these are my results, with the code that follows:
int____|____uint___|___Number__
334____|____318____|____1180____
317____|____306____|____1137____
321____|____347____|____1120____
307____|____318____|____1150____
298____|____311____|____1108____
313____|____332____|____1117____
304____|____368____|____1108____
364____|____316____|____1099____
428____|____300____|____1099____
349____|____315____|____1105____
348____|____305____|____1113____
299____|____303____|____1117____
298____|____319____|____1114____
307____|____302____|____1103____
358____|____301____|____1107____
304____|____305____|____1109____
310____|____319____|____1106____
319____|____304____|____1101____
306____|____321____|____1195____
304____|____345____|____1173____
perhaps everyone who does a test should post their code for it so there can be further scrutinization. For example, a previous test I saw had a division of 7 of the int which would force the result to be truncated, similar to a Number being rounded (which in the test it wasn't). It really ought to be Apples to Apples ... and make sure you don't have other processes on your computer that may comprimise the results
code:
package {
import flash.display.MovieClip;
import flash.utils.*;
public class Benchmark extends MovieClip
Posted by: xtyler at June 16, 2006 12:35 PM{
public function Benchmark()
{
for (var i:int = 0; i {
test();
}
}
internal function test():void
{
var startTime:Number = getTimer();
run();
trace( Number(getTimer() - startTime) );
}
internal function run():void
{
// change below iterator type to int, uint, or Number respectively
for (var i:Number = 0; i {
}
}
}
}
URL: http://codext.com
The above test was performed on the FlashPlayer 9 that ships with Flex2 Public Beta3, on an Intel PC
That may also make a difference.
Posted by: xtyler at June 16, 2006 01:39 PMURL: http://codext.com
Many things can affect the performance test, the compiler, the player and even the machine. Look at the two functions below, which runs faster?
private function test_whileUint() : void
{
var x : uint = 0;
while ( x++ }
private function test_while2Uint() : void
Posted by: Arrix at July 1, 2006 04:26 AM{
var x : uint = 0;
while (x }
URL: http://anotherblog.spaces.msn.com/blog/cns!E9C5235EBD2C699D!438.entry
Grant,
Have you questioned Adobe regarding the performance
Posted by: Terence at July 28, 2006 03:03 AMdifferences with those 3 types?
URL:
Has something changed recently with Flash Player 9 Updastes? I experience now that uints and ints are much faster that Number types are. Anybody else? I use uints in for loops instead of Numbers and it's a lot faster.
Posted by: sascha/hdrs at December 1, 2006 09:02 AMURL: http://hiddenresource.corewatch.net/
ints are faster and preferable for loops and other calculations where the number will never have a decimal place.
Once you start using calculations that add decimal places to the int(like division/multiplication or adding non integer numbers) then you get a slowdown since the result basically has to be rounded. Notably, it seems using an int is faster to get a whole integer than using Math.round() on a number (or so it seems from preliminary test).
As it stands now, uint is still very slow, even for loops.
Posted by: Jacob Correia at January 5, 2007 05:51 PMURL: http://www.saydesign.com
For the last few months, I've been writing all of my classes using uint, under the assumption I was optimizing! I'm glad I read this before I continued.
Posted by: Vernon Morris at June 28, 2007 08:36 AMURL: http://www.mathstore.net
The whole point of using "int/uint" is making your code more readable, not only gaining better performance. If you guys need better performance, why don't use have C-pgm language to build things hehe
Posted by: Ozgur Uksal at January 11, 2008 11:37 AMURL:
My expectation and reading lead me to believe that these types would in fact be more memory efficient which I assumed would make things faster. Are the memory benefits still true if not the speed? Also, if this was a shortcoming of an earlier Flash Player 9, I wonder if today in 2008 if these tests still hold true. Has anyone else tried yet?
Posted by: Andrew Blair at March 6, 2008 01:51 PMURL: http://abcd.ca/