Garbage collection (gc) in Flex/Flash for Flash Player 9 is a well known issue that has seen to be resolved in Flash Player 10. But as with all player upgrades its not always a simple process for companies out there, especially large size corporations therefore I have my hands tied with using Flash Player 10 in some of my clients apps.
So I was not overly surprised to note an increase in memory in a PureMVC MultiCore application that loads and unloads modules and utilises the Pipes utility. This was, however, something that I needed to tackle with the prospect of some of my modules being welter weight in size and thus on repeated loading and unloading had the potential of bringing a system to its knees (ok slight exaggeration).
A period of time ensued with the primary focus to try and tackle this problem. MultiCore apps with the addition of Pipes can throw in a few extra ties necessary for removal, being that its complex enough to perform all household cleanup chores for an efficient gc, the thought of removing incoming/outgoing pipes, mediators and cores can appear daunting. But it can be done and you know what, it ain’t that hard!
Reading through the PureMVC forums is an awesome way to feed off ways some people have started to tackle this issue and two dudes I fed off in the RIA/Flex/PMVC world offer awesome examples, feedback and guidance which is a must read for getting a grasp on MultiCore so check Jens Krause and Joshua Ostrom. Jens props for your tip on the definition of a clean up method in the IPipeAwareModule Interface and thanks to Sean Christmanns blog post on gc.
Phase one:
I managed to remove the necessary pipes, mediators, listeners, etc and ran a removeChild in the main application shell to remove the module and a removeCore to remove from the MultiCore framework. To check the total memory that the app consumed I ran System.totalMemory and used the invaluable Flex Profile.
Result:
Loading and unloading a module repeatedly caused a continued increase in total memory used…. damn!
Phase two:
A usual problem is running order of a sequence of events. Having a good old reference read of Colin Mooks Essential AS3 got me thinking that this could be a potential root to my lack of success, I also noted that he stated to perform removeChild() right at the end of performing all cleanups within a module. I was running removeChild prior to removeCore() ?!?
Bring on a review of the running order of cleanup, ensure time is allowed for this to occur then run removeChild() to remove the module.
Result:
it works! Load, unload a module, repeat, repeat, repeat….. System.totalMemory() is now showing no increase whatsoever!!!!
Conclusion:
There is an initial spike (dependent on module size) in total memory on the first load/unload which I am told is the code remaining in memory, this is of no major significance in my eyes due to the amount of data being retained.
The way I have tackled it is to define a method in an Interface to clean up garbage (similar to what Jens has done) and also dispatch a note to remove the module, these 2 work their way through the framework clearing and nullifying as much as possible with the garbage collection running behind the remove module note. When I instantiate both calls I also set a Timer event which should leave enough time for them both to do their house hold chores then I run a System.gc() and repeat then finally removeChild!!!!
GC still remains unpredictable (see above links) and I do not think that there is a 100% guaranteed solution but I think there is a good chance that this should enable the best shot possible to enable it to work.
Here is a mini demo application built using the PMVC MultiCore framework which demonstrates very simply (a) how to set up a modular app (b) how to integrate a the Pipes utility and communicate between a module and shell (c) how to load a module and (d) how to unload the module, perform gc and display the total memory used pre and post module removal. View Source is available. On testing I managed to get it to work effectively on each test run, others testing found that it at times did not gc (see above statement) so I have also integrated some interactivity to adjust the Timer length between performing household chores and performing gc and removeChild(). There is also a option to increase the amount of calls to flash.system.System.gc() and a quick total memory check option to see if gc is happening too late
Expected result should be the pre/post total memory panel displaying from the second load/unload onwards the same value for post garbage collection.
http://www.newtriks.com/apps/flex/PipeGarbageCollection/GarbageCollectingPipes.html
* Notes *
- You will not see the benefit of this process until you export a release version in Flex as opposed to running the debugger version.
- Garbage Collection in Flash Player 9 (I feel) still maintains elements of unreliablity, however, in comparing two of my applications one most definitely resulted in memory bloat when unloading and loading modules, the second application did not! SUCCESS
Other Reading:
http://developer.mozilla.org/en/docs/MMgc#How_MMgc_works

9 Comments
Excellent job, Simon!
Just to clarify one key statement for your readers:
“There is an initial spike (dependent on module size) in total memory on the first load/unload which I am told is the code remaining in memory…”
The FlexBuilder help has this to say (Advanced Flex Programming / Creating Modular Applications ):
“When a module is loaded by the Flex application for the first time, the module’s SWF file is transferred across the network and stored in the browser’s cache. If the Flex application unloads that module, but then later reloads it, there should be less wait time because Flash Player loads the module from the cache rather than across the network.”
So, although Flex GC may have released its reference to the loaded module, it will still consume system memory until the browser has flushed its cache. This is seen as a positive thing from a reuse standpoint if you create more instances later, but may not be what you want if you’ve loaded a huge module, only want to use it once and then wish to get rid of it altogether. That might actually require talking to some external JavaScript in the browser to tell it to flush its cache. I don’t even know if that’s possible. But it does explain why sometimes after loading and unloading a module, you still see some memory gone missing.
-=Cliff>
Thanks Cliff for that. Also I would like to offer my logic as to why the gc only works in a release-build. Lukesh on Twitter queried this and my only explanation is that the debug swf will hold onto all references for debugging purposes and therefore gc will fail? If anyone has an alternative explanation I would love to hear it
Hi Simon,
You might want to checkout the Fabrication utility[1] that we released. In fabrication the module’s facade instance is disposed when unloading the module. A “shutdown” notification is fired before the facade is disposed to allow any custom cleanup to happen inside the module. Typically, a command can register with this notification to execute cleanup within the module.
peace,
darshan
[1] : http://www.codedrunks.com/index.php/2008/09/12/fabrication-simplified-puremvc-multicore-modules/
Hey Darshan that sounds awesome I will be sure to check it out!
Simon
Thanks Simon,
I am following your guidelines and wanted to clarify tools we can use to verify success. If I need to test a release build does this mean that I cannot use Flex Profiler to confirm objects have been garbage collected and must rely on outputting pre/post memory totals as you have?
Thanks,
Greg
Hey Greg,
Yes Flex Profiler should do you.
Using the Flex Profiler
Cheers,
Simon
Thanks Simon,
this was very helpful. I built an all Actionscript application using PureMVC/Pipies/StateMachine then moved into using PureMVC/Pipies/Fabrication. I struggled with memory issues for days, pored over results from the Flex profiler and finally was re-reading your post when I noticed you remove child AFTER starting the gcCycle. Wow!!! That was the trick. Since I am not using the Flex module loader I was following what I thought was the correct sequence. BTW you should check out Fabrication. It really simplifies using pipes and I think it allows for a cleaner structure.
Thanks again
Greg
Great post. I wanted to check the sample code, but the link to your demo does not work. Can you fix that?
Thanks
Vipin
Broken link fixed1
3 Trackbacks
[...] Following a discussion with Cliff my new methods should also solve some potential issues within this app (thanks for the tips mate ). One niggle in my side was that for the application to load the [...]
[...] Following a discussion with Cliff my new methods should also solve some potential issues within this app (thanks for the tips mate). One niggle in my side was that for the application to load the module [...]
[...] das man sehen kann was und wie sie es programmiert haben (now how) hier vielleicht noch was? Garbage Collection in a MultiCore Modular Pipes Application AS3 GarbageCollection Utility Flex User (<– ist unsinnig?) Garbage Collection and Memory Leaks [...]