A few points to keep in mind:
- Garbage collection only kicks in when your app requests memory; Flash will try to recover some memory from your app before requesting another memory page (an allocation of around about 1MB) from the OS. Because your garbage collection is kicking in quite often, it suggests that your app is taking up more memory than you think
- The GC works based on references:
var s:Sprite = new Sprite()
creates a reference to a Sprite
. var s2:Sprite = s
creates another reference. For the memory that your Sprite
takes to be considered for garbage collection, both s
and s2
need to be set to null. If they're local variables, this will happen automatically when they go out of scope (e.g. if they're declared in a function, at the end of the function)
- Once all references to an object are cleared, the allocated memory can be recovered. Sometimes, however, you can have a problem with circular references - where 2 objects hold a reference to the other, but nothing has a reference to them
- To get around this, the GC has 2 phases, generally speaking: the mark phase, and the sweep phase. The mark phase will start at the root of your app (the stage), and try and touch every object that it can. Everything that's not touched is assumed to be dead and can be collected. All "dead" objects are cleaned up in the sweep phase.
- The mark phase is super slow, so you want to try and avoid it as much as possible, by essentially keeping your memory use static.
To help the GC:
- Clear your event listeners, or use weak listeners (which don't add references)
- Clear your explicit references - implement a
destroy()
or a dispose()
method that you call when you want to get rid of something, and null
everything that's an object
- As mentioned, reused objects using an object pool
- Some objects, like
BitmapData
and XML
can be immediately destroyed (BitmapData.dispose()
and System.disposeXML()
). If it's only used for setup, or can be reloaded, get rid of it. NOTE: if you're using Starling, and you create Textures
from Bitmaps
, then you probably don't need the original, unless you want to deal with lost contexts, but you can probably just load everything back in.
- Be careful of hidden allocations:
cacheAsBitmap
is allocating a bitmap in the background, ditto for filters
; Array.splice()
is creating a new array etc
- Watch out for any object creation that happens in loops etc
I wrote a class ages ago to help track memory leaks (http://divillysausages.com/blog/tracking_memory_leaks_in_as3), but you should be able to get even more in-depth using Scout - take a memory snapshot, play around a bit, then take another one; you can compare the two and highlight any created objects, including (I think) where they're being created.
Another point to keep in mind is if your device actually has enough memory to run your app in the first place - e.g. if your app (assuming everything is optimised etc) takes 100MB of memory, but you only have 80MB available, the GC will be continuously running to try and allocate the last 20
System.gc()
anywhere? You can manually call garbage collection using that method in AIR, though it is highly recommended you not do it. Regardless, without seeing some kind of code, I don't think we will be able to help much here. – Geisha