Types in AS3: ints not so fast, uints slow!

UPDATE: These findings are not relevant in more recent versions of the player. Please see this article for more recent results, and to run the tests for yourself.


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).

Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

24 Comments

  1. 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.

  2. 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.

  3. 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!

  4. 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.

  5. Darrin Massena June 15, 2006 at 11:32pm

    Thanks for the great info, Grant. Could you tell us a little about the system you performed these timings on?

  6. 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.

  7. 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.

  8. 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

    {

    public function Benchmark()

    {

    for (var i:int = 0; i

  9. 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.

  10. 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++

  11. Grant,

    Have you questioned Adobe regarding the performance

    differences with those 3 types?

  12. 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.

  13. 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.

  14. 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.

  15. 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

  16. 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?

  17. Might be time to see if this holds true for Flash Player 10 RC

  18. I discovered the same facts by myself while working on my chess engine (http://www.flashchess3.com) and it’s still true for Flash10.

    uint is ridiculously slow; int makes sense for all integer math. I wrote some more on http://www.richnetapps.com/as3-performance-optimization/

    Another interesting finding was that using vectors in Flash 10 does not bring any performance benefits over arrays as long as data is always strongly typed (e.g. avoid something like “var x:int=myArr[0][0]”)

  19. I’ve once noticed that when I use ‘Number’ in large calculations and keep adding other integer numbers it often traces no integers anymore but numbers like: 4.00000000001 or 3.99999999998 this screwed up a project after running for a while and it took me ages to find the problem. So beware of using Number everywhere.

  20. I can back the experience stated above and I wish more Flash developers would actually think about matters like these. Makes a difference in case of the larger projects, e.g. AIR apps.

  21. Allthough this issue surely have been mentioned already, both here and on Sho’s blog, I would like to reinforce it once again.

    It’s great that you present these differences but at the same time it’s a bit misleading.

    Saying that ints are slow cause you use them in calculations where they’re internally converted to numbers is not very useful.

    Int should only be used in cases where they will not be converted to numbers, like loop iterators, indexes etc.

    It’s also important to note that these data types have an important job in making the code easier to understand. For example, a number that is not allowed to be negative should have the type uint for clearification.

    It’s only when the variables are used repeatedly, like in enterFrame loops, you should consider changing the type to increase performance.

    cheers

  22. Very useful article

    Thanks man

  23. hah, now I see why HaXe defines UInt as a simple typedef of Int 🙂

  24. I really dont understand uint performance, I !used to! use it wherever I could for better performance 😀 and it was wrong.. I think it’s probably because of uint is used for colors, but still I thought its better when it’s not signed.. I was wrong, good to know.. Thanks for this very useful test .)

Leave a Reply

Your email address will not be published. Required fields are marked *