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.

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

Leave a Reply