If you attended my session about bytecode inlining at FITC Toronto you might remember that I said I have a document covering a lot of common optimization techniques.
After talking to so many of you and getting nice feedback I decided to release it in a state which is a work in progress.
My main idea is still to put this into a Wiki so everybody can share his or her knowledge. Since I am pretty busy the next weeks I do not know when this will happen so for now I hope you get some use out of the PDF.



Thanks Joa, will compare it to my own experience.
A wiki on as3 optimisation is indeed a great idea. Two thumbs up!
Thanks Joa.
Hello, very nice that you gather all this stuff.
I was looking at 2.3 Casting and wondered why the ‘as’ operator was not mentioned. So I run a few (very simple) tests.
As it turns out using the as operator on my machine with 9.0.115 is the fastest. Strange enough, using a cast slower on my machine then doing nothing.
From fastest to slowest (in my simple setup):
(_a[i] as Point).x = 2;
_a[i].x = 2;
Point(_a[i]).x = 2;
Could you include the ‘as’ in the tests and maybe check if you correctly marked the casted one as being faster then doing nothing?
Greetz Erik
Hi Erik,
there is a simple difference between Cast(obj) and obj as Cast. The “as”-cast will convert your object to null if the type does not match. For instance trace((new Point as MovieClip) == null); will return true. Doing the same like this trace(MovieClip(new Point)); will throw an exception.
Now it is very important how you test and which player you are running. The “as”-cast will work faster in the debug version of the player because there is much more overhead for exception handling. But the simple Cast(obj) is about 7 times faster in the release player.
That is the reason why I simply do not mention it at all.
And I think there has to be something wrong with your test since it is already common knowledge that _a[i].x is slower for a couple of reasons than Point(_a[i]).x.
Maybe you could paste what and how you tested.
Best,
Joa
Ahh, I offcourse only have a debug player installed, hehe.
That must be the reason. If Cast() would be about 7 times faster it would be the clear winner.
Thanks for your good explaination.
Greetz Erik
Joa,
Awesome post! There’s definitely some good detailed information in that PDF. One thing that really struck me is the test code you put in to get around the millisecond limitation of the getTimer() call.
Btw, in true wiki and community spirit, here’s the link to some of the research I’ve done on my end regarding matter. (Along with plenty other reference citations such as Matt Chotin/Ted Patrick’s talk which my research was built upon.)
http://www.iheartair.com/?p=71
Thanks again for the outstanding materials!
Thanks for releasing this Joa. This will be a real help.
I’m getting the same results as Erik, and I’ve tried both the debug player and the non-debug player (on a PowerPC Mac).
On my machine, casting with a function at a million iterations takes 1500 ms, not casting takes 1000 ms, casting with “as” takes 500 ms, and assigning to a typed variable without an explicit cast takes 250 (!) ms… give or take up to 100 ms for each test.
Here is my test: (uncomment the technique that you want to try)
var i: int = 0;
var iterations: int = 1000000;
var arr: Array = new Array();
for (i=0; i<iterations; i++) arr[i] = new Point(i,0);
var prevTime: int = getTimer();
for (i=0; i<iterations; i++) {
/* Explicit casting with a function: */
//Point(arr[i]).x++;
/* No casting, access variable with string: */
//arr[i].x++;
/* Explicit casting with ‘as’: */
//(arr[i] as Point).x++;
/* No explicit casting, assign to variable then access member: */
//var p: Point = arr[i];
//p.x++;
}
var curTime: int = getTimer();
var delta: int = (curTime - prevTime);
print(delta+”"); // call some function to print a string
Are your results different? Should I be trying something other then incrementing a member variable?
Hey, I did some more tests and I think I might see where you got your results from. It seems that arithmetic expressions are ambiguously typed before compile time, but can be strongly typed after compile time using what looks like casting, but doesn’t actually result in any casting at runtime.
var i:int;
var j:int;
arr[i+j]; // the expression returns a Number, which is used to as an array index
arr[int(i+j)]; // the expression returns an int, without any runtime casting. Fastest.
arr[(i+j) as int]; // the expression returns a Number, but then is cast at runtime to int. This version is significantly slower, because it’s the only one that casts at runtime.
If, however, we use an array index that is unambiguously a Number, casting it to int before using it isn’t any faster.
var n: Number;
arr[n]; // The array internally knows how to cast the Number to int.
arr[int(n)]; // This casts the same as the above line, except explicitly.
arr[n as int]; // This is a slightly slower way cast from Number to int for some reason.
What I said in my previous comment about casting objects AFTER they are retrieved from an array are still valid.
Thanks Joa,
i’ve used your pdf more times than I can remember now.
recently used it to do some real time edge detection (can see it here: http://lukewalsh.co.uk/blog/2008/05/real-time-edge-detection-in-flash.html)
(currently requires a webcam)
Improved the speed of the algorithm hugely by changing from 2 for loops and using bitmapData.getPixel to a while loop with a byteArray. Couldnt belive how much difference that made!
great paper!
i just want to point out that try catch is only in the case slower when you fall into the catch block. if your sprite object exists, the time is nearly the same as the check against null.
but i agree that try catch should not be used for situations where a check against null could also be set. i think in this cases a test against null is clearer then try/catch.
here are my test result:
// s != null so try block is executed; n= 1000000:
// with try catch: 305
// test with null: 292
// s == null so catch block is executed; n= 100000:
// with try catch: 1623
// test with null: 10
Awesome doc, I can’t wait to see those ‘To Do’s filled in.
For anyone interested, I squeezed a couple more ms out of the 2D loop by replacing the boolean with an increment/decrement variable and using strict equals. It’s about 30ms faster on a 2000×2000 image.
while(true){
color = bitmapData.getPixel(x, y);
x += i;
if(x === width){
if(++y === height) break;
i = -1;
} else if (x === 0){
if(++y === height) break;
i = 1;
}
}
Thanks for this, Joa - very helpful! :)