I found a few good coding tips. The following are few important basics that would help a learner to learn the fundamentals of actionscripting. What we can learn from all these benchmarks is that by accurately choosing the right way to code certain time critical functions, we can greatly improve the flash player performance. The best approach is to isolate those very cpu-intense routines and try to apply as many of these advices as possible and also running your own tests for your specific problems.
Cheer and enjoy
Basic Optimizations:
When talking about code optimizations we usually refer to speed improvements and not very much to memory savings as today, even not so recent computers, have good amount of memory for our flash programs(128mb is more than enough for most programs and today the standard for a new machine is 512mb)
>> Variables
One of the most important optimization tip is to always declare local variables using the keyword var. Local variables are faster to access for the player and are destroyed when the function returns.
An example of not-so-good code would be this:
function doSomething()
{
mx = 100
my = 100
ar = new Array()
for (y=0; y < my; y++)
{
for (x=0; x < mx; x++)
{
i = (y * mx) + x
arr[i] = i
}
}
return arr
}
This code is not very good because it does not declare those variables as local, making them slower to access and leaving them alive after the function has finished.
A better version would be this:
function doSomething()
{
var mx = 100
var my = 100
var ar = new Array()
for (var y=0; y < my; y++)
{
for (var x=0; x < mx; x++)
{
var i = (y * mx) + x
arr[i] = i
}
}
return arr
}
In this case all variables are defined locally and are faster to access. This is very important as the function runs a 10.000 iterations loop! When the function returns, all local vars will be destroyed saving resources.
>> onEnterFrame events:
the onEnterFrame event is very useful for developers as we can run code continuously at the frame rate set in the SWF.
Back to the days of Flash 5 it was a pretty common technique to use many different of these handlers.
Actually it is not reccomendable to attach many of these event handlers all over the movie clip because this can lead to spaghetti code and also it can significantly degrade performance.
Most of the times using one single onEnterFrame can be a good solution: just one main loop that takes care of the various operations to carry on.
Another simple tip is to set the fps parameter to a reasonable value: remember that the higher is the fps the more CPU power you will need to execute your code in every frame.
Values between 25 and 35 fps can be good to for executing pretty complex code in every frame even on slower machines and it is not desirable to exceed the value of 60fps (unless there's a specific reason)
>> Bitmaps vs Vectors:
Talking about graphics it is very important to choose the right approach before starting.
Flash seamlessly works with vector art as well as images but these two have very different impact on the flash player.
In using vector graphics try to simplify the shapes as much as possible eliminating redundant points. This will help in reduce the amount of calculations that the player has to compute for each vector shape. Another important aspect is the usage of outlines, which can definitely kill your performance. Whenever possible try to avoid them.
Using alpha values < 100 can also have bad impact on your general speed, so if you experience noticeable slow downs go hunting all those alpha values in your movieclips!
Moreover if you really need many sprites on screen and many animated art you may want to consider bitmap graphics.
Flash is not really a champion of speed in handling bitmaps, (for example compared to his elder brother Director) however images are faster than vectors.
Even if Flash supports GIF, JPG and PNG formats the latter seems to render faster than the others, therefore it is recommend using PNG whenever possible.
>> Movieclip visibility:
Very often you can have a large number of offscreen movicelips that are waiting their turn to come into the visible screen area.
When dealing with offscreen stuff it is important to understand that the flash player still consumes a certain amount of resouces for each of them. (doesn't matter if they are one frame only or animated)
One of the best solutions to this problem is to have an empty frame in your movieclips where you can gotoAndStop(), freeing up some work to the flash player.
Please remember that setting the visibility property ( _visible = false ) doesn't work as the movieclip still consumes some player time.
>> Arrays:
Another important tip to optimize looping in an array is to use the for in loop instead of the usual for or while syntax.
Code like this:
for (var i in arr)
{
if (arr[i] > 50)
{
// do some processing here
}
}
has proved to be faster than this code:
for (var i=0; i<10000; i++)
{
if (arr[i] > 50)
{
// do some processing here
}
}
by a 30% ratio! Not bad as a speed improvement!
>> Single vs Multiple var declaration
Whenever possible try to assign values to your variables using multiple assignment.
This can speed things up pretty nicely.
If you have in a loop something like this:
a = 0
b = 0
c = 0
d = 100
e = 100
Use this instead:
a = b = c = 0
d = e = 100
>> Attaching moviclips: for loop vs. while loop
A typical program loop where you attach movieclips to a target mc.
Using the while loop instead of for results in better performance, and if you're also
reading data from an array (this is shown in the next benchmark) then the for in loop should be the best choice.
So instead of using:
for (var i=0; i<1000; i++)
{
// code here
}
You should use:
var i=-1
while (++i < 1000)
{
// code here
}
>> Var name lookup
This test shows how important is saving name lookup time especially when inside a looping structure.
Instead of calling Math.random() at every cycle, define a reference to it and use it in the loop, this will save you time because the function name is resolved once, before entering the loop.
Example:
var num = null
t = getTimer()
for (var i=0; i < MAX; i++)
{
num = Math.floor(MAX) - Math.ceil(MAX)
}
t1.text = "Always lookup: " + (getTimer() - t)
is not as good as:
t = getTimer()
var floor = Math.floor
var ceil = Math.ceil
for (var i=0; i < MAX; i++)
{
num = floor(MAX) - ceil(MAX)
}
>> Declaring var in loops vs. declaring before loops
Before running this benchmark we thought that declaring a local var before a loop
structure could save some xtra time, but tests proved the exact contrary.
// Inside
t = getTimer()
for (var i=0; i < MAX; i++)
{
var test1 = i
}
t1.text = "Inside:" + (getTimer() - t)
// Outside
t = getTimer()
var test2
for (var i=0; i < MAX; i++)
{
test2 = i
}
>> Using nested if
Whenever using complex conditional expressions you can optimize the code by breaking them into single nested conditions.
This way you don't have to evaluate all the expressions all the times.
The following code is what we used for the benchmark: even if the conditional expressions are pretty simple the speed increse is significant.
Also you can notice that the expression that evaluates as false is in 3rd position, so you may even get better performance when it is placed in 2nd or 1st position.
MAX = 20000
a = 1
b = 2
c = -3
d = 4
var i=MAX
while(--i > -1)
{
if (a == 1 && b == 2 && c == 3 && d == 4)
{
var k = d * c * b * a
}
}
var i=MAX
while(--i > -1)
{
if (a == 1)
{
if (b == 2)
{
if (c == 3)
{
if (d == 4)
{
var k = d * c * b * a
}
}
}
}
}
>> Accessing local vars (This vs. With vs. Reference)
Local variables and objects can be referenced in more than one way.
We've tested two ways to do it and found out that the usage of the keyword this produces the worst results.
More speed can be achieved using with operator.
obj = {}
obj.a = 1
obj.b = 2
obj.c = 3
obj.d = 4
obj.e = 5
obj.f = 6
obj.g = 7
obj.h = 8
obj.test1 = useThis
obj.test2 = useWith
MAX = 10000
function useThis()
{
var i = MAX
while(--i > -1)
{
this.a = 1
this.b = 2
this.c = 3
this.d = 4
this.e = 5
this.f = 6
this.g = 7
this.h = 8
}
}
function useWith()
{
var i = MAX
while(--i > -1)
{
with(this)
{
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
g = 7
h = 8
}
}
}
>>Math.floor() vs int()
Instead of using the new Math library floor() function try the old-fashioned int()
Compiling for flash player 6 using Flash MX 2004:
One of the interesting things with FMX 2004 is that the actionscript compiler has been improved under many aspects.
The new compiler does a better job with both global (player 6 and 7) and local register (player 7 only) making some of the tweaking presented here less important.
You can see by yourself, from our benchmark table, that some very interesting results were achieved.
The most noticeable improvements we noticed were that _global variables seems to be a lot faster than timeline variables and nested loops now perform way better than before.
Also you will notice that almost every test run faster than the Flash-MX compiled version.