Drawing API Memory-Leak in Flash 10.1
When trying Rune Hunt in the new 10.1 version of the Flash Player I noticed a HUGE performance drop. In the old player it would take about 27ms on my system (debug build) to update the game’s state and render the next frame. In Flash Player 10.1 this changed: The time it took to calculate a frame started fluctuating and increased to 48ms on average.
A member of the Flash Player Engineering team replied to my inquiry about known performance issues:
General actionscript performance is not any slower in 10.1 than 10.0 from our testing, it must be something particular in your code which exhibits the problem. Do you have a reproducable test code or a url you can point us at?
So I tried to isolate and reproduce my problems. It seems that my problems are caused by a Memory Leak in the Drawing API. I wrote a simple test application to illustrate the issue and hopefully find a work-around.
//... there`s a buffer as rendertarget and a flare private var _flare:BitmapData = null; private var _buffer:BitmapData = null; //each frame I render the flare 100 times into the buffer for(var i:int = 0; i < 100; i++) _buffer.draw(_flare, null, null, BlendMode.ADD);
In the 10.0 player there is no memory fluctuation caused by this code. But in the 10.1 player each draw-call allocates new memory. The total memory is increasing linearily until the garbage collector kicks in. This of course effects the performance.
In all browsers and on all systems that I tested the memory leak was present in the new player – but the way the garbage collector handled it varied so the graph isn’t always as clear. You can test it for yourself. And here’s the source for the test application.
My guess at what happens: BitmapData.draw() method accepts IBitmapDrawable an interface that is implemented by all DisplayObjects and BitmapData objects. If you pass a BitmapData object however it seems like memory gets allocated based on the size of the render target. This memory is not reused or instantly freed but has to be collected by the garbage collector.
Knowing this there’s a neat workaround: If you wrap the BitmapData in a Bitmap before you draw it you can avoid the bugged code and the memory keeps steady!
//wrap _flare in a Bitmap (do this only once!) _flareBmp = new Bitmap(_flare); //now instead of _flare render _flareBmp for(var i:int = 0; i < 100; i++) _buffer.draw(_flareBmp, null, null, BlendMode.ADD);