As you build a Flash project, take a gander at the amount of memory FlashPlayer.exe is using (i.e. simply looking at FlashPlayer.exe in the Task Manager in Windows). If you see the memory usage going up and up and up as you interact with it and never down then there’s a memory leak, caused by a number of factors. My very first AS3 project did this.
Adding, Removing, and Memory Usage
Another goal in learning AS3 was to easily add and remove objects with a small bit of reusable code – and once removed, stay completely removed forever and ever so that the memory can be freed. This gets a bit difficult with AS3 however. AS3 introduces a new memory implementation (search for Garbage Collection around the Inter Webs) that can be somewhat difficult to manage, because Actionscripters are not used to worrying about it.
The first cause of this leak that I found was when I remove objects and the memory it had taken up doesn’t free itself. Worse yet, the object was still listed in my debugger! gSkinner has written extensively on this topic, but the basic gist is – if you remove an object that is referenced by something else, it will not be removed from memory until all of those references are removed as well. Even more simply – nine times out of ten – when you use nothing but addChild() and remvoe with removeChild() on a dynamically created object, it is not removed from memory. This may not seem like a huge deal when we’re dealing with a few small squares and circle sprite on the stage. But when its 1000 sprites, and they each contain 1mb bitmaps, and they are each objects that are doing their own internal loops or some other sort of interactive functionality…removing them and freeing up that memory becomes key to the success of your application.
The trick is two fold – remove any references to the object, and null the object itself. In continuing my previous post…
var _views:Object = new Object();
createShape();
trace("Does my shape exist?: " + _views.myShape);
removeShape(_views.myShape);
trace("How 'bout now?: " + _views.myShape);
killShape(_views.myShape);
trace("Surely its gone now...: " + _views.myShape);
function createShape():void {
var myShape:Shape = new Shape();
myShape.name = "myShape";
_views[myShape.name] = myShape;
addChild(myShape);
}
function removeShape(view):void {
removeChild(view)
}
function killShape(view):void {
delete _views[view.name];
view = null;
}
Note that even after removeChild() our object still existed. That means that the Garbage Collector won’t remove it. But after removing the reference to the object in _views by physically deleting the “myShape” property, and then fiving the myShape variable a value of null, the object is suddenly gone. The memory will be freed up next Garbage Collector looks at it and we don’t have to worry about it ever again.
What we now have are the fundamentals for adding and removing objects we’ve created. I use this add/remove code in just about every AS3 project, before writing a single line of code:
function addView(view):void {
_views[view.name] = view;
addChild(view);
}
function removeView(view):void {
removeChild(view);
delete _views[view.name];
view = null;
}
function removeAllViews():void {
for each (var view in _views) {
removeView(view);
}
}
Check out the removeAllViews() function. If an object exists in the _views container, it’ll be killed.
We can expand on addView() to include staged instance as well. For instance, if I have a MovieClip already created on the stage, I could add it to my _views object with the following, where “stagedMC” is a named MovieClip instance on my FLA’s stage. The benefit is that the MovieClip can be dynamically interacted with in the exact same way as all of my dynamically created objects – for instance, when using removeView():
addStagedView(stagedMC);
removeView(stagedMC);
function addStagedView(view):void {
_views[view.name] = view;
}
In the context of our example, our completed app might look like this:
var _views:Object = new Object();
createShape();
trace("Does my shape exist?: " + _views.myShape);
removeShape();
trace("How 'bout now?: " + _views.myShape);
function createShape():void {
var myShape:Shape = new Shape();
myShape.name = "myShape";
_views[myShape.name] = myShape;
addChild(myShape);
}
function removeShape():void {
removeView(_views.myShape);
}
function addView(view):void {
_views[view.name] = view;
addChild(view);
}
function addStagedView(view):void {
_views[view.name] = view;
}
function removeView(view):void {
removeChild(view);
delete _views[view.name];
view = null;
}
function removeAllViews():void {
for each (var view in _views) {
removeView(view);
}
}
Note that there can be a good thing about this whole “can’t remove it” problem. If there’s an object that you never want to have removed from memory, just make sure there’s always a reference to it and it will always exist!
- AS3 My Way: Intro
- AS3 My Way: Name Everything!
- AS3 My Way: Adding, Removing, and Memory Usage
- AS3 My Way: A little bit of MVC
thank you very much it is very helpful