removeChild() leak in DisplayObjectContainer?

I’ve been trying to track down a leak in my game (which uses OpenFL 3.3.5 / Lime 2.6.4, and targets html5), and the leak appears to be coming from DisplayObjectContainer.

In the Chrome profiler, I noticed that the number of Bitmap objects in use was steadily increasing over time (from an expected ~250 up to over 950 a few minutes later). I’m pulling Bitmaps out of a sprite map to use as animation frames (these get parented to a DisplayObjectContainer on the Stage), so it makes sense that more get created over time; however, frames that are no longer needed are removed via removeChild(), and all references are nulled.

The profiler showed that most of the existing Bitmaps were in DisplayObjectContainer’s __removedChildren array. As a test, I commented out the line that adds the removed children to this array; with that change, my Bitmap count never exceeded ~250 objects.

Looking at the code, it seems that this array is only relevant when the DOMRenderer is used:

@:noCompletion @:dox(hide) public override function __renderDOM (renderSession:RenderSession):Void {

	[...truncated...]

	for (orphan in __removedChildren) {
		
		if (orphan.stage == null) {
			
			orphan.__renderDOM (renderSession);
			
		}
		
	}

Is there a reason removed children need the extra render pass when the DOM is used, versus, say, the Canvas? More importantly, is there a reason this array would not be getting cleaned up correctly? I see it being spliced in all the render calls (including Canvas, which is what my game is using).

Thanks for any help you can provide! =)

Are you using Assets to reference your bitmaps? Have you checked if it is cached there? Do you use other libraries that could be caching?

Thanks for the swift response!

We aren’t using Assets. We have a custom loader and a sprite map class, and both only cache BitmapData. The only class that ever caches the Bitmap itself is the parent class (which derives from DisplayObjectContainer).

We have an hypothesis that the DisplayObjectContainer is being removed from the display tree before the render call that splices __removedChildren, and that something is holding a reference that is keeping the whole lot from getting GC’d. I’m looking into this now to see if that’s what is happening.

Hey Dan,

did you find any solution to your problem? I belive I am having a similar issue

Yes, we eventually discovered that Actuate tweens were maintaining unexpected references to DisplayObjects. We took better care to clean those up (typically via Actuate.stop( aDisplayObject, null, false, false )), and saw a decrease in memory issues. If you are using the Actuate library, perhaps you are running into something similar?

Hope it helps!

2 Likes

jeah I found actuate leaking aswell, good to know that workaround works! But still the simple removeChild() for a newly instantiated DisplayObject seems still to be leaking. The only way to get around that at the moment is an objectpool for me, but thats not ideal.