Archive for May, 2009

More on Finding Memory Leaks

It seems that the most common scenarios involving memory leaks are the ones involving loading and unloading multiple SWFs like modules and sub-applications. Every day, we learn more and more about how the player manages memory and its other idiosyncracies, so it is time for another summary.
When debugging suspected memory leaks when loading/unloading SWFs, I generally do the following:
1) Set up the app or a test harness to load and unload the SWF multiple times (at least 3) and force a garbage collection pass after each unload or unload, then use the profiler to see how many copies of the module’s xxx_FlexModuleFactory or the subapplication’s xxx_SystemManager are in memory. If more than 1, keep loading and unloading and see if that number continues to grow. Any module or SWF that introduces a new component with styles will register those styles with the StyleManager and stick around forever the first time it loads. You can prevent that from happening by pre-loading the styles in the main app or via a CSS module. A second copy might stay around if it was the last thing loaded because the player or FocusManager might still be hanging onto it. If you see more than 2, that’s definitely a leak and you should use the profiler to find the leak.
2) After several loads and unloads, I take a memory snapshot, then do more loads and unloads and take another snapshot. I clear all filters, remove percentages, sort by class name and compare manually the number of instances of every class. They should match exactly, except maybe for a few Strings and sometimes, WeakReference. Everything else is suspect and deserves investigation.
3) Once I think I got all references to the SWF cleaned up, I next run several loads and unloads in the debugger and check the console. I am looking for lines in the debug output that start with:
[UnloadSWF]
That tells me that the player thought everything was cleaned up and unloaded the SWF. Note that it may not say that right away, even after GC requests as sometimes the player has internal references to a SWF that get cleaned up “later”. If I don’t see that, I go back to step 2 and compare memory snapshots looking for other things that might be leaking
4) Now that I’m convinced that even the player thinks it is ok to unload the SWF, if System.totalMemory is still increasing, the final test is to export release builds for all swfs and run them in a release player. The debugger player seems to hang onto debug information in the SWFs and can skew System.totalMemory. In recent tests, once I get past step 3, the release player’s reporting of System.totalMemory is much more acceptable, capping at a much smaller and acceptable maximum memory value.
5) Once you get past that, some of you might still see memory attributed to the player still growing when using OS tools to examine the player process. That remains an open area of investigation by the player team. For Internet Explorer, one often finds that minimizing IE causes its claim on memory to shrink, implying that it is something to do with IE’s memory management and not the Flash Player or your application. We don’t know of any way to programatically force IE to give up that memory. We also have seen reports of other browsers reporting memory growth even though Flash thinks things should be unloaded. If you can reproduce that in a small test case, file bugs with those test cases.