Preamble
Actionscript is, for the most part, a dynamically typed language, which means that the types (i.e. String, int, GameObject) of variables are checked at run-time rather than at compile-time like they are in C and Java. This is supposedly beneficial to the programmer since such a language is more flexible. All sorts of crap like this is valid:
var i = new GameObject();
i = "1";
As you can see it’s possible to change the type of a reference to something entirely different. This can generate type errors at run-time since later you may try to call i.update(). Although this example is very obvious real world examples can be more nuanced and thus more complicated to find and fix.
Casting and using ‘Strict Mode’ is a technique to essentially make Actionscript a little bit like a statically typed language. The performance boost comes from firstly doing as much as possible at compile-time (thus less at run-time) and secondly helping the process of type checking by casting.
Code
package {
import flash.display.Sprite;
import flash.utils.getTimer;
import flash.system.System;
public class Main extends Sprite {
/* Document class that contains the test code
*/
static const LENGTH = 100;
private var gameObjectsArray:Array;
private var gameObjectsVector:Vector.;
private var t:uint = 0,dt:uint = 0;
public function Main() {
init();
test();
}
public function test() {
testArray();
testVector();
}
public function testArray() {
/* Call the update method for each element in the array once with cast and once w/o
*/
var i:uint = 0,j:uint = 0;
t = getTimer();
for (i = 0; i < 100000; i++) {
for (j = 0; j < LENGTH; j++) {
gameObjectsArray[j].update();
}
}
dt = getTimer() - t;
trace("Array without casting: "+dt);
t = getTimer();
for (i = 0; i < 100000; i++) {
for (j = 0; j < LENGTH; j++) {
GameObject(gameObjectsArray[j]).update();
}
}
dt = getTimer() - t;
trace("Array with casting: "+ dt);
}
public function testVector() {
/* Call the update method for each element in the vector once with cast and once w/o
*/
var i:uint = 0,j:uint = 0;
t = getTimer();
for (i = 0; i < 100000; i++) {
for (j = 0; j < LENGTH; j++) {
gameObjectsVector[j].update();
}
}
dt = getTimer() - t;
trace("Vector without casting: "+dt);
t = getTimer();
for (i = 0; i < 100000; i++) {
for (j = 0; j < LENGTH; j++) {
GameObject(gameObjectsVector[j]).update();
}
}
dt = getTimer() - t;
trace("Vector with casting: "+ dt);
}
public function init() {
/* Define and fill the array and vector
*/
var i:uint = 0,m:uint = 0,dm:uint = 0;
gameObjectsArray = new Array(LENGTH);
for (i = 0; i < LENGTH; i++) {
gameObjectsArray[i] = new GameObject();
}
gameObjectsVector = new Vector.(LENGTH,true);
for (i = 0; i < LENGTH; i++) {
gameObjectsVector[i] = new GameObject();
}
}
}
}
package {
public class GameObject {
/* Dummy object to use for the test
*/
public var x:Number = 0,y:Number = 0,vx:Number = 0,vy:Number = 0;
public function GameObject() {
}
public function update() {
x+=vx;
y+=vy;
}
}
}
Just out of interest I decided to throw in a comparison of Arrays and Vectors.
Results
Strict mode on
| Test |
Array w/o cast |
Array with cast |
Vector w/o cast |
Vector with cast |
| 1 |
1832 |
1432 |
1862 |
1476 |
| 2 |
1888 |
1430 |
1800 |
1461 |
| 3 |
1773 |
1468 |
1798 |
1458 |
| 4 |
1768 |
1434 |
1798 |
1462 |
| 5 |
1769 |
1432 |
1834 |
1461 |
| Average |
1806 |
1439.2 |
1818.4 |
1463.6 |
Strict mode off
| Test |
Array w/o cast |
Array with cast |
Vector w/o cast |
Vector with cast |
| 1 |
1776 |
1637 |
1820 |
1676 |
| 2 |
1826 |
1639 |
1942 |
1664 |
| 3 |
1779 |
1638 |
1822 |
1667 |
| 4 |
1778 |
1638 |
1820 |
1665 |
| 5 |
1872 |
1636 |
1812 |
1661 |
| Average |
1806.2 |
1637.6 |
1843.2 |
1666.6 |
Hmm… This is very interesting indeed; Vectors seem to be slightly slowing things down. Of course I wasn’t expecting a major improvement since the use of a Vector instead of an Array doesn’t speed up the arithmetic in update(), but I don’t see why Vector without a cast couldn’t have been as quick as Array with a cast.
This is in fact so interesting that in warrants another quick test. A test between Array and Vector, as it turns out Vectors are ~60% quicker if only used for number crunching i.e. they only contain Numbers.
Conclusion
As I had expected Vectors are overrated, they don’t offer a performance improvement unless the Vector is only used for number crunching. To be brutally the Vector is rather useless in most situations plus because it’s a top-level class you get a clash when you want to create a Vector (as in the Mathematical kind) class.
Always have strict mode on and cast your objects.
Leave a Reply