The reason for this issue is a lot more interesting than you would expect.
Examine the following code, it includes seven tests:
Here are the results:
- 864 - compare with literal constant int
- 866 - compare with int
- 1358 - compare with vector length (size fixed)
- 1376 - compre with vector length (size dynamic)
- 3159 - compare with object member
- 3152 - compare with static object member
- 11855 - compare with array length
Why do you suppose the last one is so terribly slow when compared to the rest?
It is not because the Array re-calculates the length each time, that would be silly.
Read this:
length property: A non-negative integer specifying the number of elements in the array. This property is automatically updated when new elements are added to the array. When you assign a value to an array element (for example, my_array[index] = value), if index is a number, and index+1 is greater than the length property, the length property is updated to index+1.
The reason is in the implementation
//Implementation
public function get length():uint
public function set length(value:uint):void
The other six tests use a regular public member of a class.
Array's use getter and setter functions to retrieve the length value.
If you continue to elaborate the test, you will see function calls cost precious time.
When you need more performance, you sometimes have to rely on inline code.
That is is true almost every time. That is because the processor has to 'jump' to a different area in the code, create a new scope and some additional reasons.
Why is inlining considered faster than a function call?
If you check the length implementation for vector, you will see it is just a public member unlike array (getter and setter) functions. Getters and Setters are better for extensibility, they can make your life a lot easier if you decide to inherit from a class, setters can also prevent certain errors by checking the values. Nothing beats a public property for speed.
package regression
{
import flash.display.Sprite;
import flash.utils.getTimer;
/**
* ...
* @author Arthur Wulf White
*/
public class Check_Loop_Speed_1 extends Sprite
{
//BIG_NUMBER == 100,000,000
public function Check_Loop_Speed_1()
{
var i : int = 0, j : int = 100000000, time : int = 0;
var vector: Vector.<Boolean> = new Vector.<Boolean>(100000000, true),
vect2 : Vector.<Boolean> = new Vector.<Boolean>(100000000),
obj : Object = new TestObject(),
arr : Array = new Array();
arr.length = 100000000;
//test 1
time = getTimer();
for (i = 0; i < 100000000; i++) { }
trace(getTimer() - time);
//test 2
time = getTimer();
for (i = 0; i < j; i++) { }
trace(getTimer() - time);
//test 3
time = getTimer();
for (i = 0; i < vector.length; i++) { }
trace(getTimer() - time);
//test 4
time = getTimer();
for (i = 0; i < vect2.length; i++) { }
trace(getTimer() - time);
//test 5
time = getTimer();
for (i = 0; i < obj.val; i++) { }
trace(getTimer() - time);
//test 6
time = getTimer();
for (i = 0; i < obj.val2; i++) { }
trace(getTimer() - time);
//test 7
time = getTimer();
for (i = 0; i < arr.length; i++) { }
trace(getTimer() - time);
}
}
}
class TestObject
{
public var val : uint = 100000000;
public const val2 : uint = 100000000;
}