Maximizing flash performance
Date: 14 February 2010With the birth of AS3, actionscript -and flash in particular- grew up and became more and more suitable for professional web and desktop based solutions. But like any scripting (or programming) languages you need to keep an eye on your performance. Building astonishing and complex projects is ofcourse very satisfying, but can be also a big pain in the ass when your client uses a machine from the early nineties.
What a client expects
Developing huge 3d projects with fullscreen videos won't render that well on machines that already have a lot of trouble with starting notepad. But as long as the client knows flash can achieve miracles, but it can't cure deseases, you're in the right zone.Project cycle
Nevertheless always be on top of your game as it comes to performance. If you start new (large) projects and keep focussing on performance from the very first line of code you write and monitor your result alongside the entire process you won't get any unpleasant suprises once your client tests your final version.
Illustrated on the graph above, the further away you are in a project the more difficult it gets for the developer to add new functionality in it's code.
So if you could be warned in an early stage of the flashproject cycle that a particular update is using too much system recourses or the framerate is at an unacceptable level, you could take measures and therefor avoiding the 'last minute' adjustments. Which -we all know- will only decrease the quality of your code and the project itself.
This exactly is the reason why you need to keep monitoring and making your code use as little resources as possible. Click the 'read more' link below, to see a few examples and best practices in maximizing flash perfomance
Minimize the number of event listeners.
Remove event listeners when an event cycle is completed.For instance Event.COMPLETE and ProgressEvent.PROGRESS.
You can use weak-references, but weak references are a last-resort solution, best is to remove your listeners when necessary
examples
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
function loadComplete(e:Event):void {
e.target.removeEventListener(Event.COMPLETE, loadComplete);
}
btn.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
function mouseOver(e:MouseEvent):void {
e.target.removeEventListener(MouseEvent.MOUSE_OVER, mouseOver);
e.target.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
}
function mouseOut(e:MouseEvent):void {
e.target.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
e.target.removeEventListener(MouseEvent.MOUSE_OUT, mouseOut);
}Only use a minimum of one Event.ENTER_FRAME
This extends the previous tip, by default try to use as low as event listeners as possible, this includes the onEnterFrame event.wrong
var redCircle:Circle = new Circle();
var blueCircle:Circle = new Circle();
addChild(redCircle);
addChild(blueCircle);
redCircle.addEventListener(Event.ENTER_FRAME, redCircleEvent);
blueCircle.addEventListener(Event.ENTER_FRAME, blueCircleEvent);
function redCircleEvent(e:Event):void {
e.target.x += 5;
}
function blueCircleEvent(e:Event):void {
e.target.x += 3;
}
the right wayvar redCircle:Circle = new Circle();
var blueCircle:Circle = new Circle();
addChild(redCircle);
addChild(blueCircle);
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
function enterFrameHandler(e:Event):vodid {
redCircle.x += 5;
blueCircle.x += 3;
}Dispose unused bitmapData
Whenever a bitmap (or a DisplayObject containing a bitmap) is removed from the displaylist, the bitmap and it's BitmapData should be removed from the memory.More information about the dispose() method
example
var bmp:Bitmap;
var ldr:Loader = new Loader();
ldr.load(new URLRequest("image.jpg"));
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
function imageLoaded(e:Event):void {
e.target.removeEventListener(Event.COMPLETE, imageLoaded);
bmp = e.target.content;
addChild(bmp);
setTimeout(deleteBitmap, 3000);
}
function deleteBitmap():void {
removeChild(bmp);
bmp.bitmapData.dispose();
bmp = null;
}
Close NetStream and NetConnection
When a NetStream is initialized and the attached Video object is removed from the displaylist, make sure the attached stream and it's connection are closedexample
var connection:NetConnection = new NetConnection();
connection.connect(null);
var stream:NetStream = new NetStream(connection);
stream.client = { };
var video:Video = new Video();
addChild(video);
video.attachNetStream(stream);
stream.play("movie.flv");
setTimeout(removeVideo, 10000);
function removeVideo():void {
stream.close();
connection.close();
removeChild(video);
stream = null;
}Unload() those unused Loaders
Whenever a loader isn't used anymore nor will be used in any upcoming events or functions, it's wise to unload the Loader instance.So the garbage collector can pick up on this empty object and frees it allocated memory
example
var ldr:Loader = new Loader();
ldr.load(new URLRequest("image.jpg"));
addChild(ldr);
setTimeout(deleteImage, 3000);
function deleteImage():void {
removeChild(ldr);
ldr.unload();
ldr = null;
}If you want to unload a SWF containing additional actions, you can use unloadAndStop() to unload the loader and delete any attached references in the loaded SWF. See adobe help docs for more informationReference counting
When using non-primitive types (anything other then String, Number, uint, int and Boolean) you are always passing around reference to the object. When removing a variable you are removing the reference, not the actual object. Grant Skinner wrote a nice article about itI wrote a small function to iterate infinite through an object it's children and deletes it's references:
function _delete(obj:*):void {
for (var key:* in obj) {
_delete(obj[key]);
delete obj[key];
}
obj = null;
}
In the following example using the above function:
var obj1:Object = { foo: "bar" };
var obj2:Object = new Object();
obj2.foo = obj1.foo;
trace(obj1.foo, obj2.foo); // returns "bar bar"
_delete(obj1);
_delete(obj2);
trace(obj1.foo, obj2.foo); // returns "undefined undefined"The objects 'obj1' and 'obj2' are empty, but although you can't access them anymore, there is still a reference available between eachother.Hower whenever the Flash Player will start it's "Mark Sweeping" process, the references will be deleted and the memory will be allocated.
Keep an eye on your memory / framerate
I wrote my own memory / framerate monitor, that sits in either one of the four corners of the flash player.In the nearby future I'll put it only for sharing purposes.
For now you can create your own monitoring tools using the System.totalMemory and the stage.frameRate methods.
Or you can use the Memory Monitoring Component by Adobe (also available as a global SWC)
By monitoring your memory and framerate you can see whenever a memory leak occurs or when your player uses above average CPU (framedrops)
Comments
Amazing! Not clear for me, how offen you updating your www.kolnedra.com.
2010-02-14 19:30:00 Socco http://www.pscdns.biz/