15
Jun
2006

Avoid ints in ActionScript

The more I play with Flex, the more I learn, and the more I learn about ints, the less I want to use them. I’ve concluded that I’m going to stop using ints unless I really need them.

Reason 1: Numbers may actually be faster than ints

Surprising, but true. ECMAScript Edition 4 is designed to be a language that is as compatible as possible with earlier versions of ECMAScript. As it turns out, this makes it difficult to ensure that math works “correctly” in seemingly innocuous cases.

public function timingTest() : void
{
	var intTime : Number;
	var numberTime : Number;
	
	var i : int;
	var j : int = 0;
	
	intTime = (new Date()).time;
	for (i=0; i<10000000; i++)
		j = (j + 15) / 7;
	
	intTime = (new Date()).time - intTime;
	
	var n : Number;
	var m : Number = 0;
	
	numberTime = (new Date()).time;
	for (n=0; n<10000000; n++)
		m = (m + 15) / 7;
	
	numberTime = (new Date()).time - numberTime;
	
	var message : String = 
		"int version: " + intTime + "ms\n" +
		"Number version: " + numberTime + "ms";
	
	Alert.show(message);
}

Which version do you think wins? On my machine, the int version takes 331ms, while the Number version takes 291ms. Why is this? Let's look at the following expression:

j = (j + 15) / 7;

What happens if you start with the value j = 2^31 - 1? In some languages, you would run into overflow issues as soon as you add 15 to it. ECMAScript, however, has a looser concept of numbers. The system is supposed to move smoothly from ints to doubles as needed. Because of this, virtually all math is done internally as Number, not as int.

Given that everything is being done as a Number anyway, the extra cost of converting from int to Number and back again takes even more time, which is why the int version is slower.

There is a second counterinuitive reason for using Number over int, which is that Number actually lets you store integral values more precisely than ints do...

~

Reason 2: Numbers have more bits

This is a surprisng fact about numbers that is obvious in hindsight. Let me tell you how I ran into it.

The Date object has a property called time that gives the number of milliseconds since midnight, Jan 1, 1970. Because it is an integral value, and because there are no longs in ActionScript, I just assumed that the return type was really an int (or possibly a uint):

var time : uint = (new Date()).time;

What's the bug? A quick back of the envelope calculation will tell you that there have been more than 2^32 milliseconds since Jan 1, 1970, which results in an overflow. Stupid mistake.

But it makes you wonder... If you can't fit that many bits into an int, and if ActionScript doesn't have the concept of a long, why can you do this without overflow or losing precision:

var time : Number = (new Date()).time;

Underneath the hood, a Number is equivalent to one of the following numeric types:

  • int
  • uint
  • IEEE double

I always shy away from using doubles for integer math, because you are never guaranteed that it will keep all of your digits. In my mind, a double can store bigger ranges of numbers than ints (because of the exponent) at the cost of less precision.

As it turns out, in the case of ActionScript, a double can store bigger ranges of numbers (because of the exponent) and keep more precision than any of the integral values. This is because ActionScript doesn't have a 64 bit integer type.

The IEEE double format looks like this:

  S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  0 1        11 12                                                63

There is one sign bit, 11 bits for the exponent, and 52 bits for the integral portion of the number. Thus, you can store numbers that are quite a bit larger than will fit into an int without losing any precision.

When would you ever want to use an int?

There are legitimate uses for ints.

  1. When you want to save memory. (although this should only impact you when you have tons and tons and tons of numbers to store)
  2. When you want to force an integral value (e.g., var i: int = j / 2)
  3. To reduce the chance of bugs as you map integral values from client side to server side. (e.g., int fields in value objects).

That having been said, I'm going to stick to Numbers for most of my code from now on.

21 Responses to “Avoid ints in ActionScript”

  1. Grant Skinner

    Wow! Thanks for posting this Sho. I just posted the results of some simple tests you prompted me to run on my blog:
    http://www.gskinner.com/blog/archives/2006/06/types_in_as3_in.html

    The results for uint are downright shocking.

  2. Geoffrey Williams

    Very interesting. I’ll have to run some similar tests on my code to see if it makes an impact.

    Thanks.

  3. Grant Skinner

    updated with some new tests, as per your suggestion. Now to get back to real work. :)

  4. Tink » Blog Archive » Use the Correct Type for the Job

    [...] Have you been put off from using the correct type for the job after reading the recent infomation from Sho and Grant about speed of uint and int compared to Number? Obviously this information is worth noting, but the 2 post titles ‘Avoid ints in ActionScript‘ and ‘Types in AS3: ints not so fast, uints slow! ‘ are bound to put some poeple off using them at all and sticking with Number, which they shouldn’t do. [...]

  5. BIT-101 Blog » Blog Archive » Optimization: When to do it.

    [...] There have been some posts by Sho and Grant regarding the relative speeds of int, uint and Number in AS3. Very interesting stuff, and important to know for the professional programmer. But Tink brings up some good points about the value of using the correct types for the job, regardless of the performance differences. [...]

  6. Nicolas

    That’s actually good news for haXe :) In fact haXe has both Int and Float types, which are different constraints enforced by the compiler. For Flash Player before 9, both Int and Float becomes numbers. For Flash9, I was thinking using Int = int but since there is no performance increase it’s better to use Number anyway.

  7. Arrix >> More on Number, int and uint in AS3

    As Macromedia says, int is great for loop counter. In a loop like for(var i:Type = 0; i

  8. Jacob Correia

    You should use int for your loops and any other values that will not have decimal places. Using an int as a loop iterator is faster than using a number.

    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. This explains your results above.

    Even so, the conversion is pretty fast. Change m = ((m + 15) / 7) to m = Math.round((m + 15) / 7) to simulate int rounding and you’ll see using an int seems faster than using Math.round() on a number.

  9. int vs Number « Pushing the boundaries

    [...] Posted by vijayram on February 1st, 2007 This issue was highlighted by Sho Kuwamoto sometime back who recommends to use Number where ever possible. Grant Skinner made some additional test and has posted his results here. [...]

  10. drawtree

    The title and conclusion of this post is wrong. Jacob is right. Your code has serious logical bug, and it makes your conclusion wrong.

    Refer 25p. of this document:
    http://www.onflex.org/ACDS/AS3TuningInsideAVM2JIT.pdf

    If you understand concept of explicit-type-casting you’re already know what I want to say.

  11. Sho

    To Jacob and Drawtree:

    Thanks for engaging in this discusssion!

    Not sure what the timings are these days with player 10, but (a) you’re right in the narrow sense, and (b) I still think there is an efficiency issue in the broader sense.

    Jacob’s point (and drawtree’s, implicitly) is that certain operations are faster when done as ints. That is undoubtedly true.

    However, for those of us who come from a non-dynamic language background (C / C++ / Java), the expectation is that built-in integral types are there precisely for the purposes of being faster than generic number types, even when doing things like printing them or dividing them.

    In many other languages, dividing two integers compiles down to an integer division operation which is much much faster than a floating point integer division operation. In ActionScript (as of player 9, anyway), the integers are converted to number before the division. And as for the print statement specified in Gary’s excellent talk, it’s a mystery to me why the conversion occurs. Perhaps because the signature of the print method takes an untyped argument?

    So… to summarize… I believe that the performance behavior of ints in ActionScript would be surprising to many people. Dividing two ints would normally be faster than dividing two floating point numbers, for example.

    As for the title of the post, I may have been guilty of engaging in hyperbole. Maybe it should have been called “consider using Number instead of int inside of tight loops”. I certainly continue to use ints on a daily basis for typechecking purposes.

  12. The logical consequences that never happened at controul

    [...] a BETTER one. Function inlining, mixing as3 and bytecode, optimised integer math (I do NOT want to work with Numbers); the list of possible enhancements was long. Why would anyone really need any of this? Mainly [...]

  13. Actionscript optimized types and why as3’s int sucks ass at tec.

    [...] They writer of this blog actually suggests to default to Number instead of int, because Numbers are faster in most cases avoid ints in Actionscript [...]

  14. [flash] Variables and Data types « Not just a note

    [...] / Uint * Only works in whole numbers. <Some said The Number works faster, see here, or [...]

  15. Steven

    http://lab.polygonal.de/2007/06/06/int-uint-and-number-data-type-conversion/

  16. Steven

    Sho,

    Your blanket statement that Number is better than int is not fair at all.

    Your loop is doing an int() cast every single iteration. Of course this is going to be slow. Note the difference if you don’t divide by 7 and it doesn’t have to do a conversion.

    var now:int = getTimer();
    var j:int;
    var i:int = 10000000;
    while (i–)
    {
    j = (j + 15);
    }
    trace(getTimer() – now);

    41ms

    If you divide by 7

    154ms

    Obviously, doing floating point math using Number is faster than doing it with int. But doing integer math with int is MUCH faster than doing it with Number.

    If you’re using floats, use Number. If you’re using integers, use int.

  17. Sho

    Hi Steven. Good point!

    The issue is that in many languages (such as C++ or Java), (j+15)/7 *is* an integer operation when j is an int. So for those of us who come from those languages (and who see the strong typing in AS3 as a move toward those languages), this is confusing.

    Even if you argue that having this be a floating point operation is ‘better’ than having it be an integer operation, a modern compiler should be able to analyze the code to discover that the result of this operation is stored in an int and do an integer version of the division operation.

    If I remember correctly, the player team investigated this approach, and found that it was difficult to get strictly correct behavior in edge cases (like dividing by NaN, etc). As a trade-off, they did an intrinsic conversion to Number in many cases that aren’t strictly necessary.

    They may have improved this in more recent version of the VM. I haven’t worked at Adobe for 2 years, so I don’t really know what’s going on these days.

  18. Christopher Cantrell

    The adobe-created classes like ArrayList use “int” instead of “Number” for loop counts and list indices. I figure they know what they are doing; I’ll follow suit.

  19. Sho

    Hi Chris. Is that you?

    Anyway, the info on this page is old, and I’m sure that the performance characteristics are different now.

    Also, incrementing integers and using them for array indexing was always (slightly) faster than the same operations with Number. It was always things like division where int was being converted to Number and back again in order to have consistent behavior in all edge cases.

  20. AS3 Code Optimization – write smarter run faster!:) « pigiuz

    [...] per cui preferire Number non sono solo di velocit√†, ma anche di capacit√† e precisione. Lo zio kuwamoto infatti spiega come, al contrario dei linguaggi di programmazione “standard”, in [...]

  21. Avoid ints in Actionscript | D_

    […] 블로그를 둘러 보다 흥미로운 포스팅을 보았는데요. Actionscript 로 작업할시 숫자 타입의 int 를 사용을 자제 […]

Leave a Reply