Finding Flash ActionScript 3 Resource Leaks

Even though programming in ActionScript 3 in the Flash engine gives you access to a garbage collected language it is still easy to leak resources and kill the performance of your application. I’ve been looking into some issues with an application I’m working on as well as general debugging techniques and wanted to summarize them in a post.

First, the two main resource leaks that have come up for me in game development:

  1. Leaking objects in the display list.
  2. Leaking event listeners, especially ENTER_FRAME.


Leaking display list objects

This is a straightforward leak that can happen to any DisplayObject you add to a DisplayObjectContainer. Even if the object is off screen, alpha is zero, or if its visible property is set to false the object is still being updated by the Flash runtime. It is using memory and CPU cycles. Make sure you clean up your objects by removing them from the display list when they are not in use.

Here’s a small, simple code snippet for recursively walking a display list. If you suspect a DisplayObjectContainer is leaking objects, you can use this small utility function to count how many display objects exist in all children. If it doesn’t go down at all, you may be leaking objects (of course it depends on the use case of your software).

public function walkList(obj:DisplayObjectContainer):Number
{
var result:Number = 0;
if (obj == null || obj.numChildren == 0)
{
return 0;
}

result += obj.numChildren;

for (var i:int = 0; i < obj.numChildren; i++)
{
result += walkList(obj.getChildAt(i) as DisplayObjectContainer);
}

return result;
}

Leaking event listeners

This can be harder to track down than leaking display objects. Here’s the big thing that may not seem obvious to people at first – removing an object from the display list, even such that there are no more references to it, does not automatically destroy it or any of its event listeners. If you add a listener through addEventListener() you must remove it through removeEventListener().

By far the worst case of this are rogue ENTER_FRAME events that are still executing on objects you think are removed and gone.

I spent some time trying to figure out how best to track these issues down. The AS3 event model allows you to, for most events, insert an event listener in a parent object in the display hierarchy and basically monitor events as they go by. For example, if one of your child objects has a MOUSE_DOUBLECLICK event you can put the same event on your stage with the third parameter to addEventListener() set to true (capture). You can then print out what object the event is actually going to by using Event.currentTarget inside of the stage event listener.

Guess what though? You can’t capture ENTER_FRAME events in that way. You’ll have to recursively walk the display list again looking for objects that have the ENTER_FRAME event registered. If they have no parent reference then they are likely orphaned (again, depends on your software use case).

Or perhaps better yet – don’t use ENTER_FRAME at all for complex Flash software and write a traditional game update loop. That’s what I’ve done in my engine. I now only use ENTER_FRAME for hacking together prototypes.

As an addendum, here are some gotchas regarding AS3 that I learned about in my recent research:

Apparently creating static utility functions, especially math helpers used in tight loops, is significantly worse performance wise than pasting the code into the loop (aka ghetto inlining) even if complex constants would have been precomputed in the helper. Lesson: static lookup is slow.

If you can avoid it, do not call functions on class references that are typed by one of their parent classes. E.g. if you have a variable of type MyObject, try not to reference it through the global root class Object or any other parent class that may exist. This defeats the purpose of object oriented programming in many ways but for your most performance sensitive code the virtual method table lookup destroys performance.

3 Responses to “Finding Flash ActionScript 3 Resource Leaks”

  1. Ben Fhala says:

    great article. I’ve been working on a library that i hope will be useful that deals exactly with the topic your talking about here. i hope you like it and i would love to get your feedback on it check it out:

    http://fla.as/ec/

    just from reading down to your issues with Static methods i would skip the EC and work directly with the LEC. let me know what you think about it would love to get your feedback. the EC is more for smaller projects or when performance isn’t as much as an issue as much as just monitoring everything in one global view.

    in a nut shell instead of working directly with events you are passing them to a manager that builds an index for them and exposes it to you to manage it in any way you see fit.

  2. Mark Cooke says:

    Hi Ben,

    Cool library! That looks very helpful.

    I haven’t been working in Flash recently but when I come back to it I’ll be sure to check it out.

  3. Ben Fhala says:

    by the way since the last comment we made another major update that makes it even better (we think ;) so when you get to it don’t forget to download an updated source ;) (now you can: pause,add a cluster of events, use external loggers/debuggers and other performance improvements ;)

Leave a Reply