May 29, 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.

December 6, 2008

Tree and Lazy or Paged Data

The Flex Tree control (mx.controls.Tree) is the subject of many complaints. It's pretty finicky if you don't use a dataProvider where the data is "all there". Any attempts to lazily load in nodes must be coded carefully. If you don't tweak the DataDescriptor properly it won't work.

Tree does have one major flaw, and that is that it can't handle a dataProvider that throws ItemPendingErrors as data sets that come from LiveCycle DataServices do. Tree uses an undocumented pair of classes to effectively linearize the current set of open nodes into a dataProvider that its base class (List) can handle. The code for that was scrambled together at the last minute and wasn't deemed sufficient enough for the AdvancedDataGrid, so our AdvancedDataGrid team developed their own HierarchicalCollectionView classes and beefed them up to handle ItemPendingErrors. Due to various scheduling and logistical issues, Tree was left by the side of the road, stuck with its undocumented HierarchicalCollection classes that can't handle ItemPendingErrors.

At the tail end of Flex 3, several customers were in need of a Tree that could handle ItemPendingErrors. THe shortest route to such a thing was to create a subclass of Tree that could handle the AdvancedDataGrid's HierarchicalCollectionView. Example and source code are below. You'll see the acronym "DMV" throughout because the AdvancedDataGrid and HierarchicalCollectionView are part of the Data Management and Visualization package (which requires the Professional versions and/or more money) so those of you trying to go the cheap route won't be able to leverage this code. Also, you won't need this unless your data source throws ItemPendingErrors when an attempt is made to fetch data that hasn't been paged in yet, and unless you developed your own, you are using one of our data services which also cost you some money.

The example comes with a test tool we wrote that throws lots of ItemPendingErrors so we can try to find all the code paths that are sensitive to it. Unlike most of the posts on my blog, this one actually got some QA time, but the usual caveats apply.

Run Example
Download Source

November 21, 2008

Faster DataGrid Horizontal Scrolling

Lately, I've heard many complaints about horizontal scrolling performance in DataGrid. Vertical scrolling has been optimized, but horizontal has not. I found a bit of time to put together how to subclass DataGrid and try to optimize horizontal scrolling. I'm sure there's bugs and I don't know if I'll have time to fix them and the usual caveats apply.

Hope it helps. It should work with any Flex 3 SDK version.

Download Source

In the example, the top DataGrid is not optimized, the bottom one is. Make the screen bigger and you'll start to see and feel the difference.

Run Example

September 5, 2008

Using the Flex Builder 3.x Profiler

I've been getting lots of questions about memory leaks lately. I finally found some time to put my techniques for analyzing memory leaks into writing.

Instead of using PowerPoint, I actually created a SWF so you can use the SWF to both view the presentation and learn how to use the Profiler. I cover the differences between profiler memory, System.totalMemory and process memory and show how I analyze the two most common memory leak scenarios.

Run Presentation

As usual, caveats apply.

The SWF also demonstrates an approach to another topic I've heard about often, and that is how to do XML-driven or data-driven UI. The presentation in this SWF is controlled by an XML file. A single engine parses the XML and creates the UI widgets as dictated by the XML. To change the presentation, all I have to do is change the XML. I can also add new widgets easily. Source is available here:

Download FlexBuilder Project

The SWF also demonstrates a technique for improving startup time. Because our blog system is painful to use, I don't like uploading more than one or two files per blog post, but this presentation had more than a dozen images. So, instead of loading images externally, I embedded them into the SWF, but normally, that delays startup by the download time of all of those images. To get around that, I pack all the images into frame 3 of the SWF so that Flex can get up and running while the images download at the end of the SWF. I can get away with that because the images are not needed right away.

Hope this helps.

August 19, 2008

Flex Authority Magazine

I think I can finally say I got something published! Gordon Smith and I contributed to the first issue of Flex Authority, a new magazine (made of actual paper!) that focuses on Flex and AIR. We hope to be regular contributors. The link to find out more is: http://www.flex-authority.com/. Buy your subscription today. We won't make any money from it, but this post is to thank them for working with us and to help them get the word out so they can make some money.