Introduction
This article is primarily concerned with ActionScript 3 and generally specific to AVM2. Most suggestions would apply to ActionScript 2 as well, and I've noted those tips that differ between AS2 and AS3.
With the advent of ActionScript 3.0 (hereafter "AS3"), the Flash Player realized significant performance gains. A few years ago, I ran some performance tests comparing JavaScript to AS2. ActionScript was noticably slower in every benchmark, usually in the range of 300% or more time required to perform large calculations. Even animation - Flash's wheelhouse - was slower. AVM2 and AS3 have changed that, and levelled the playing field to a large degree.
That said, the greatest single contributor to slow performance of Flash applications is poorly written ActionScript. Below you'll find 20 tips to help you write faster applications. Please note that the motivation behind each tip is performance, not transparency or best practice. A performance optimization might directly oppose a best practice, and will very often create opacity in your code. It's your decision as to what takes priority in your application: performance, transparency or best practices.
Much of the information presented here will provide only negligible gains as regards performance when used in small-scale code operations. However, when a developer tweens 3500 raindrops every frame, every line of code needs to be parsed and pared to the sharpest, smallest point possible.
Before I begin, learn to benchmark your code. There are many approaches, including specialized software or components like frame-rate meters, but the simplest trick I know is to measure the time a loop containing the statements to be tested takes to operate. After all other setup is performed, on the line immediately before the loop, call the getTimer method and store it in a variable. Execute your loop (I usually start with 1000 iterations to avoid script timeout, then increase by a factor of 10 until I get a measurable metric). Immediately following the loop, evaulate the difference by invoking getTimer again and subtracting it from the first. E.g.,
var start:Number = getTimer();
for(var i:int=0;i<1000;i++){
// statements to evaluate
}
trace(start-getTimer());
5:
The Tips
Multiple conditionals are faster than stacked operators
When using stacked operators in an evaluation statement, each one is evaluated before returning the result. Using conditional statements allows the VM to stop checking as soon as it can - when further evaluation is no longer needed.
if(var1) if(var2) if(var3)
is faster than
if(var1 && var2 && var3)
Object literals are faster than the new operator
Strings, Numbers (including int and uint), and Boolean objects are usually instantiated using literal notation (var str:String = "text"). Objects and Arrays are often instantiated using the "new" operator - this is seldom necessary (only in the case of a fixed-length Array), and is slower.
var list:Array = [1,2,3];
is faster than
var list:Array = new Array(1,2,3);
For loops are faster than while and do-while loops
In AS3, the fastest loop is the for loop (not for.. or for each..in). While and do-while are slightly slower. Note that this is a marked contrast to both ActionScript 2 and JavaScript, where while and do-while are about 3 times faster than for loops. Also, the int datatype is faster than uint or Number (see tip #16).
for(var i:int=0;i<1000;i++)
is faster than
var i:int=0;
while(i<1000)
The in operator is faster than hasOwnProperty
To test if an object has a publically available property, use the "in" operator instead of the hasOwnProperty method.
prop in Object
is faster than
Object.hasOwnProperty("prop")
5: The one-dot rule
When accessing nested variables, anytime a variable requires even one level of scope shift to discover, and is referenced more than once, save it to local variable. In drawing classes, you'll often see Math.PI / 2 referenced within loops that might iterated hundreds of times each frame - that value should be stored in a local variable. Note that this is not true when referencing member methods. Saving Math.PI to a variable is appropriate; saving Math.round to a variable is not.
var var Number = container.child.x;
textfield.text = var1;
container.child2.x = var1;
is faster than
textfield.text = container.child.x;
container.child2.x = container.child.x;
6: Dynamic classes are slow - use a public object variable instead
Avoid dynamic classes. Consider a public variable datatyped to Object instead.
public class MyObject{
public var variables:Object = {};
}
is faster than
public dynamic class MyObject{
}
7: Perform work in enterframes
This one may seem counter-intuitive, and most tutorials and help-boards are peppered with warning against enter frames. Surprisingly, performing heavy calculation during the enterframe can help "balance the load" and lead to improved performance.
8: Standard string methods are faster than Regular Expressions
Regular Expressions are a great tool and can make complex tasks much easier. However, standard string methods are almost always faster.
var parts:Array = longString.split("|");
is faster than
var parts:Array = longString.match(/(.*?)\|/gm);
9: Use plain text instead of XML where possible
XML requires the VM to implement a parser, where evaluating plain text requires no special operation. Where possible, use strings or plain text rather than XML.
10: Work from the top of the stack
When manipulating arrays, work is performed from the top-down. That means always work from the end of the array, rather than the beginning. Pop and push are faster than shift and unshift.
MyArray.push(myVar);
is faster than
MyArray.shift(myVar);
1 enterFrames are faster than timers and intervals
Flash handles enterFrames as part of it's native update process - timers and setInterval calls are not. Actions performed during the enterFrame event perform better than equally frequent Timer events.
addEventListener("enterFrame",myFunc);
is faster than
myTimer.addEventListener("timer",myFunc);
1 Use local variables
When flash detects a variable, it looks first at the local scope - the context of the currently evaluating function. If not found, it looks at the next "highest" scope, and repeats, until the variable is discovered (or undefined is returned). Always use local variables when possible. Note that function arguments are considered local variables.
function getMinutes(){
var myVar:uint = 6000;
return getTimer() / myVar;
}
is faster than
var myVar:uint = 6000;
function getMinutes(){
return getTimer() / myVar;
}
1 Constants are faster than variables
If a variable is unlikely to change, use the const declaration rather than the var declaration.
const URL:String = "http://www.experts-exchange.com";
is faster than
var URL:String = "http://www.experts-exchange.com";
1 Use the as operator instead of casting
Use the "as" operator when possible, instead of casting via constructor.
var child:MyClass = event.currentTarget as MyClass;
is faster than
var child:MyClass = MyClass(event.currentTarget);
15: E4X is extremely slow
E4X is another great tool that can offer drastic savings in development time, but when used on large data sets its performance tends to suffer. Surprisingly, looping through an XML tree is often much faster than complicated E4X structures.
for each(var node:XML in myXML){
if(node.@myProp == "value"){
if(node.@anotherProp == 12){
react();
}
}
}
5:
6:
7:
is faster than
var nodes:XMLList = myXML.(@myProp=="value").(@anotherProp==12);
for each(var node:XML in nodes){
react();
}
16: int - uint - Number
Of the three Number datatypes, Number is the slowest, int is the fastest, and uint is slightly slower than int. This applies to simple evaluation only, such as when looping (always set the iterator to the int datatype). However, performance varies when using more complex evaluation - for example, division operations are performed more quickly on Numbers than ints or uints - I suspect this is because all numbers are cast as Number when performing division, because the return must contain the possibility of a float.
for(var i:int=0;i<10000;i++)
is faster than
for(var i:Number=0;i<10000;i++)
17: Use bitwise methods when possible
Figuring out the math behind bitwise operation can be intimidating, but there are simple ways to use bitwise functionality that can really speed up your code.
var n:Number = 93745298347.230498;
var m:Number = n|0;
is faster than
var n:Number = 93745298347.230498;
var m:Number = Math.foor(n);
18: Use array.join instead of string concatenation
String concatenation is very slow - use arrays and array methods where possible.
var myArray:Array = [];
for(var i:int=0;i<1000;i++){
myArray[i] = "text";
};
var myString:String = myArray.join(" ");
5:
is faster than
var myString:String = "";
for(var i:int=0;i<1000;i++){
myString += "text ";
};
19: Don't evaluate in a loop's conditional test
The condition expression in the for loop is commonly used to evaluate a variable or property - this expression should be a predefined local variable when possible, so that it doesn't need to be evaluated during each iteration of the loop.
var l:uint = myArray.length;
for(var i:int=0;i
0
收藏