Tom Sugden: General Archives

February 22, 2010

How to Unload Modules Effectively

It's well known that unloading modules in Flex can be tricky. The principle is simple: remove all references to the module and it will become eligible for garbage collection. The harder part is that those references can exist in unexpected places. Did you know that the code generated by the Flex 3 MXML compiler when processing a CSS stylesheet can sometimes cause a module to be pinned in memory? There are a number of causes of memory leaks like this, but they can be avoided by following certain practices.

This blog post demonstrates how to unload a Flex 3 module effectively that is styled and localized. It applies several of the techniques described in Alex Harui's earlier post, What We Know About Unloading Modules. Note that Flex 4 (out now!) and Flash Player 10.1 both bring improvements in the area of memory management, such as the modular styles sub-system in Flex 4, so not all of the points below are applicable to Flex 4 projects.

Getting Started

The best way to understand module unloading is to create a sample project and run some tests. Here's a sample Flash Builder project that uses Flex SDK 3.5 to demonstrate the effective unloading of a module. A number of practices are applied and these are described later.

The sample project contains an application that loads and unloads a module repeatedly, displaying the System.totalMemory reading. Click the image below to launch the application:

ExampleApp.png

You can click the "Load/Unload" toggle button to load and unload the module manually, or the "Run Stress Test" button to begin repeatedly loading and unloading the module for a given number of repetitions. A checkbox can be used to control whether or not the garbage collector is forced after each unload. When running the application from Flash Builder in debug mode, you should see the following trace produced by Flash Player when the "Unload" button is clicked:

[Unload SWF] Workspaces:MyWorkspace:ModuleUnloading:bin-debug:module:MyModuleStyles.swf
[Unload SWF] Workspaces:MyWorkspace:ModuleUnloading:bin-debug:module:MyModule.swf

This trace indicates that the module and associated compiled CSS SWF have both been successfully unloaded. When running the stress test in the release Flash Player, you should observe the memory falling after each unload and no excessive accumulation of memory, which would indicate a module unloading memory leak. The figure below shows the expected profile when a module is not unloading effectively on the left-side, with the expected profiling when unloading is successful on the right-side:

MemoryProfile.png

You can then make alterations and observe the impact on memory consumption. If you make some changes and you no longer observe this trace, then you have pinned the module in memory, creating a memory leak! Use the memory profiling features of the Flash Builder Profiler to see which objects exist before loading and after unloading, and use your operating system tools (Task Manager, Activity Monitor, etc.) to watch the real memory footprint of the browser process while running the application.

Note that when using the Flash Builder Profiler you need to be running the debug version of Flash Player, but while observing the operating system process, you need to use the release player to get an accurate picture. It's handy to have the installers for both versions to hand, or if you're running on Windows, you might install one version in Internet Explorer and the other in Firefox. The FlashSwitcher plug-in for Firefox is another option.

The rest of this article explains the practices that have been followed in the sample application to ensure the module unloads effectively. While reading it, you can refer to the comments inside the source code that highlight each practice.

Practices for Unloading Modules

Take Care With Style Tags

When the MXML compiler processes a Style tag, it generates some code for registering the specified style selectors with the StyleManager. This code produces a back-reference from the 'StyleManager' to the auto-generated class that performs the registration. If a Style element is used inside an application that is no problem, but if one is used inside a module the result is a reference to a class inside that module. This reference pins the module in memory preventing unloading.

In the sample application, you can see that a Style tag is used in the shell application for loading a CSS file that contains some type selectors and some class selectors.

<mx:Style source="app/MyAppStyles.css"/>

If you add the -keep compiled argument, then you will be able to see the style registration code that is auto-generated by the MXML compiler. Note that the specifics of the auto-generated code can change between releases, but with Flex 3.5, a file called MyApp-generate.as will be produced that has a function called _MyApp_StylesInit(), which performs the actual registration.

You'll also notice that no Style tag is used inside the module. Instead, style selectors that are specific to the module are specified in the module/ModuleStyles.css file and compiled into a SWF that is loaded and unloaded together with the module. More details on this later.

Compile Resource Bundles Into The Shell Application

In a similar manner to styles, when the MXML compiler processes some [ResourceBundle] metadata, some code is auto-generated to register the resources from the specified properties file with the ResourceManager singleton. This code creates a reference to the auto-generated class, so if it takes place inside a module, the module will end up being pinned in memory. Instead, the resources need to be compiled into the shell application or else loaded at runtime using a resource module.

In the sample application, the resources for the module are compiled into the shell application:

<mx:Metadata>
    [ResourceBundle("app")]
    [ResourceBundle("module")]
</mx:Metadata>

If the resource bundles are not large and are known at compile time, and you don't need to switch locale at runtime, then this is the simplest approach. If the resource bundles are large, unknown at compiled time or you do need to switch locale, then using resource modules is a better approach. Refer to the Flex documentation for instructions to compile resource modules. They can be loaded and unloaded via the ResourceManager.

Link Components With Default Styles (or keep all type selectors)

When the MXML compiled encounters a component that has default styling specified in a type-selector of a CSS file inside the Flex SDK or another referenced CSS file, it will auto-generate code to register those styles. If that registration happens inside a module, the module will be pinned in memory in the same way as with a Style tag.

There are two ways to avoid this. The first is to statically link components with default styles into the shell application. Then the default style registration will take place when the application starts up and not when the module is loaded. This can be seen in the sample application:

Button;
RadioButton;
CheckBox;
ComboBox;
TextInput;
DataGrid;
DataGridColumn;
Module;

Alternatively, the -keep-all-type-selectors compiler argument can be used to force the compiler to generate style registration code for all known type selectors, regardless of whether or not the components are linked into the application.

This is one of the areas of improvement in Flex 4. Instead of registering style selectors with the StyleManager singleton, Flex 4 features a revised styles sub-system that registers styles with each module, preventing the issue described above.

Link Classes with RemoteClass Metadata

When [RemoteClass] metadata is encountered, the MXML compiler auto-generates code to register the remote class mapping with Flash Player. Before Flash Player 10.1b3, this resulted in a reference that can prevent module unloading. To avoid this issue with earlier versions of Flash Player, classes with such metadata can be linked into the shell application. Then the remote class registration takes place at application start-up and doesn't pin the module in memory.

The use of HTTPService in the module appears to cause this issue, presumably because it links other classes with [RemoteClass] metadata. For this reason, the HTTPService is statically linked into the shell application too:

HTTPService;

This issue has been resolved in Flash Player 10.1b3. For earlier versions, the above work-around can be used. An alternative approach that also works is to compile the remote classes into a separate module that is loaded at start-up.

Move Focus Out of Modules Before Unloading

The Flex FocusManager holds a reference to the component currently in focus. If that component is inside a module, then that reference will pin the module in memory preventing unloading. When a module is unloaded it is necessary to move the focus onto a component outside of the module. This is the user experience that would generally be desired anyway, so the next appropriate control is in focus for the user to continue their work.

In the sample application, a TextInput has been declared:

<mx:TextInput id="textInput"/>

Just before unloading takes place, the focus is moved to this TextInput:

textInput.setFocus();

There are also cases where Flash Player will hold a reference to the last interactive control, but this will be released as the user proceeds to interact with other parts of the application.

Load Modules Into Child Application Domains

When a module or compiled CSS SWF is loaded, an application domain can be given. This is the application domain into which the class definitions inside the SWFs are loaded and stored. These class definitions can only be unloaded when no references to instances remain and no reference to the application domain itself remains. For this reason, it is important to load modules into a child application domain and not the current application domain if you wish to unload them. The current application domain contains the shell application classes and can never be made eligible for garbage collection.

In the sample application, a child application domain is created, then used for loading both the module and compiled CSS SWFs:

var childDomain:ApplicationDomain = 
    new ApplicationDomain(ApplicationDomain.currentDomain);

ml.applicationDomain = childDomain;
ml.loadModule("module/MyModule.swf");

StyleManager.loadStyleDeclarations(
    "module/MyModuleStyles.swf", 
    true, false, childDomain);

When it comes to unloading, it is important to nullify the reference that the ModuleLoader component holds to the child ApplicationDomain, so it can be garbage collected:

ml.applicationDomain = null;

For more information about application domains and their subtle nuances, refer to the following blog posts:

Use Compiled CSS for Module Styling

When the MXML compiler is used to compile a CSS file into a SWF, the generate code contains both registration and de-registration functions. This means that compiled CSS supports unloading, so it is a good approach for styling modules. Any selectors that are unique to the module can be compiled into a stylesheet SWF that is loaded together with the module, then unloaded again afterwards.

This approach can be seen in the sample application. The module/MyModuleStyles.css is compiled into module/MyModuleStyles.swf and the StyleManager is used to load the SWf into a child application domain and unload it again afterwards:

StyleManager.loadStyleDeclarations(
    "module/MyModuleStyles.swf", 
    true, false, childDomain);
...
StyleManager.unloadStyleDeclarations(
    "module/MyModuleStyles.swf");

Consider Forcing the Garbage Collector

When the unload() method is called to unload a module, there is no guarantee that it will be immediately garbage collected. If there are no remaining references, then it will becomes eligible for garbage collection (GC) and may be removed later, when Flash Player chooses to run the garbage collector. The System.gc() method will force the garbage collector to run in debug versions of Flash Player, but there is no such API for release versions at present.

There is however an unsupported hack known to prompt the garbage collector in most versions of Flash Player. This is documented, along with various caveats, in Grant Skinner's blog post:

By attempting to open 2 local connections then swallowing the resulting error, a full mark-and-sweep garbage collection is instructed:

try
{
    new LocalConnection().connect("anything");
    new LocalConnection().connect("anything");
}
catch (e:*) {} // ignore intentionally

The sample application contains a check-box that allows you to control whether or not this hack is applied after each unload. In my simple tests, the memory footprint remained lower when the hack was applied than without, but I have not conducted exhaustive testing and this technique is unsupported by Adobe. Note however that there is an enhancement request to provide an official API for forcing the garbage collector, which you are free to vote for:

JP Auclair's blog contains a detailed explanation of the Flash Player garbage collection algorithm:

Understanding the Expected Behaviour

When profiling module unloading, it is important to understand the expected behaviour and not misinterpret the memory footprint of the browser process as indicative of a memory leak. When a module is unloaded and the garbage collector has cleaned it up, the memory footprint should not be expected to return all the way to the base-line level. This is because the pages of memory that Flash Player and the browser have allocated from the operating system may not be completely empty. Blocks within these pages may have been allocated to different objects in the application. Only empty pages can be returned to the operating system. So after unloading and garbage collection you should expect some reduction, but when the next module is loaded, the holes in the existing pages will be filled before more pages are grabbed from the operating system. Overall the memory footprint is expected to be lower when applying unloading than without.

Unloading is Not Always Necessary

It should be noted that for some applications unloading is not necessary and a load-once policy may be adequate. Furthermore, some applications may require more elaborate policies, where some modules are unloaded, but the modules most frequently used by users are always kept in memory. Remember that there are many benefits to modularization, not least of which is the efficiency gains for developers working on distinct functional areas that can be developed, tested and profiled in greater isolation.

If an application has a relatively small number of modules and the overall memory footprint when every module has been loaded is acceptable, then perceived performance will be better and programming easier if unloading is not used. Similarly, if a user is only entitled to access a subset of the available modules, it may be acceptable to leave them in memory after loading. It is better to load-once-and-leave rather than unsuccessfully attempting to unload and creating a memory leak.

Light-Touch Optimization

There are many ways to optimize a Flex application to improve perceived performance and reduce resource consumption. However, optimization can often have an impact on code simplicity and clarity, so the benefit needs to outweigh this cost. The best kind of optimization has a light touch on the existing code base. Where manual clean-up code ot hacks are deemed necessary, it is best to try and isolate this code and not to allow it to spread widely through the codebase. For instance, the extensive use of dispose() methods has sometimes been advocated, but this typically complicates a large number of application classes. The example in this blog post gets by without such methods.

Conclusion

Flex provides simple yet powerful features for building modular applications, but some care needs to be taken to ensure that modules unload effectively. This article demonstrated some practices for ensuring that styled and localized Flex 3 modules do unload. These can be used to reduce the overall memory footprint of large, modular applications. The latest betas of Flash Player 10.1 and Flex 4 both introduce further improvements that help to simplify memory management, such as the modular styles sub-system in Flex 4 and the new explicit disposal APIs in Flash Player 10.1.

For more information about memory management in Flex, refer to the comprehensive series of blog posts written by Alex Harui. These are essential reading for enterprise Flex developers:

Posted by tsugden at 9:58 PM | Comments (0)

December 10, 2009

Writing Genuinely Reusable Flex Components

On larger projects and within enterprises, there's often a case for extracting a set of reusable components into a Flex library project. In theory, the same components can be reused across modules and sub-applications of multiple Flex or AIR clients, bringing greater consistency and more rapid development. However, in practice there are some common mistakes that limit the reusability of components. This post explains what makes a component genuinely reusable and highlights some techniques from the Flex SDK that can be applied to your own components to make them more reusable.

What Makes a Component Genuinely Reusable?

There are different levels of reusability, but a fully reusable component should be able to render any kind of data. It should be equally comfortable with an array of basic, dynamic Objects or a collection of concrete Kangaroos. The Flex DataGrid has this quality:

<mx:DataGrid dataProvider="{ kangaroos }">
   <mx:columns>
      <mx:DataGridColumn headerText="Name" dataField="name"/>
      <mx:DataGridColumn headerText="Weight" labelFunction="calculateWeight"/>
   </mx:columns>
</mx:DataGrid>

Notice how the dataField and labelFunction properties tell the component how to get its data from the Kanagoo objects without imposing any dependency. These are two of the mechanisms available to make a component genuinely reusable. Even if the developer has no control over the Kangaroo class itself, perhaps it's part of a 3rd-party library, they can still easily render these objects within a DataGrid.

The Data Interface Anti-Pattern

One common mistake is to insist that the data being rendered by a component implements a specific interface. For example, consider a DistributionBar component that renders a simple graph, like that shown in Figure 1.

DistributionBar.png

Figure 1 - A Distribution Bar Component

The distribution bar shows a number of regions with different sizes, each containing a label. It's tempting to configure this using an array of IRegion objects:

public interface IRegion
{
   function get label() : String;
   function get size() : int;
}

The distribution bar can then extract the size and label information for each region through this interface. The rationale for this is that the interface decouples the component from the concrete objects it renders. Anything can be rendered so long as it implements IRegion, but that so long is in fact the design flaw. By imposing the use of the IRegion interface the reusability is limited. The interface needs to be added to existing model classes before they can be rendered in a distribution bar, and worse, if the models were produced by another library or separate team, it might not be an option to change them, so they'd need to be wrapped. For these reasons, the component is not genuinely reusable.

Reusable Components of the Flex SDK

The Flex SDK contains many reusable components and this is achieved by applying a few standard approaches:

  1. Data Fields
  2. Data Functions
  3. Data Descriptors
  4. Factory Objects

These approaches are now described and the same techniques can be applied to your own components to make them reusable.

Data Fields

A data field is a String property that specifies the name of another property. For example, the labelField property of the ComboBox or the dataField and dataTipField properties of the DataGridColumn:

<mx:ComboBox dataProvider="{ items }" labelField="name"/>

The component implementation uses the data field to read the data values from the items it renders. For example:

for each (var item:Object in dataProvider)
{
    var value:Object = item[dataField];
    // do something with the value
}

This is a simple approach but it offers great flexibility. The component can render any readable property of any class of object.

Data Functions

A data function is a property of type Function that is used to specify a reference to another function. For example, the labelFunction property of the ComboBox or the dataFunction property of the DataGridColumn.

<mx:DataGridColumn headerText="weight" dataFunction="calculateWeight"/>

The component then invokes the data function, typically passing through an item of data as a parameter. For example:

for each (var item:Object in dataProvider)
{
    var value:Object = dataFunction(item);
    // do something with the value
}

This approach is similar to using a data field, but offers even more flexibility, since the function can perform calculations or formatting before returning a value to the component for rendering.

Data Descriptors

A data descriptor is an interface through which a component can analyze the items of data it renders. The developer can then pass their own implementation of the interface to the component in order to configure it. An example can be seen in the Tree component of the Flex SDK:

<mx:Tree dataProvider="{ items }">
    <mx:dataDescriptor><my:MyDataDescriptor/></mx:dataDescriptor>
</mx:Tree>

The tree can then discover characteristics of the data by querying its data descriptor interface. For example:

for each (var item:Object in dataProvider)
{
    var isBranch:Boolean = dataDescriptor.isBranch(item, dataProvider);
    // do something with the outcome
}

This approach is very powerful, but is only necessary for complex components such as the Tree. The effort of using the component is more than a simple List or ComboBox, but the component is still completely decoupled from the data it renders. If a developer needs to render a new class of object in a tree, they typically write a new implementation of the ITreeDataDescriptor interface.

Factory Objects

A factory object, in terms of component developent, is a property of type IFactory that is used to instantiate children at runtime. For example, the itemRenderer property of the List and DataGrid or the dropdownFactory property of the ComboBox.

<mx:List dataProvider="{ items }" itemRenderer="my.package.MyItemRenderer"/>

The component uses the standard IFactory interface of the Flex SDK to create new objects at runtime:

var itemRenderer:Object = itemRenderer.newInstance();

Then it passes data items into the new object through the IDataRenderer interface:

if (itemRenderer is IDataRenderer)
{
    IDataRenderer(itemRenderer).data = item;
}

This approach gives great control over the visual appearance of parts of the component. By providing custom item renderers, completely different results can be achieved. The logic for processing the item of data can be as simple or complex as needed and it can be encapsulated inside the item renderer class. Having said that, components that use factories should define sensible default values, so the component is easy to use in simple cases without setting special factories. This is the case for all the ListBase components, such as DataGrid, which uses the general purpose DataGridItemRenderer by default.

It's worth noting here that the Flex compiler has a special relationship with properties of type IFactory. When it notices such a property being set in MXML, it will automatically generate code to convert class names and in-line components into instances of ClassFactory. This makes the components easier to use, so developers don't usually need to instantiate class factories manually, but instead just specify a class name or declare an in-line component.

Conclusion

When fully reusable components are needed, it's good to remember the simple rule: a reusable component should be able to render any kind of data. This is best achieved by following the conventions laid out in the Flex SDK, such as data fields, data functions, data descriptors and object factories. It's important to resist the urge to introduce new interfaces that impose unnecessary obligations on users of your component, because to do so limits its reusability.

Postscript: Since fully reusable components tend to use mechanisms such as dynamic property lookups and function references, there are some trade-offs to consider. These techniques are slower than accessing properties of strongly-typed objects and they're not resiliant to compile-time type checking. However, the advantages of flexibility and reduced dependencies can outweigh these drawbacks for larger projects and enterprises.

Posted by tsugden at 9:18 AM | Comments (2)

September 21, 2009

Morgan Stanley Matrix at MAX

Next month at Adobe MAX 2009 in Los Angeles, Børre Wessel (Lab49) and myself will be presenting Matrix, the next-generation sales and trading platform from Morgan Stanley.

ms-matrix-1.jpg

The session is entitled, "Building Matrix – Scaling Flex for a Large Trading Application" and it will cover our experiences as we worked on the client-side architecture of Matrix, together with a large team of developers. We will discuss the patterns and practices that made the delivery possible — modularization, dependency management, performance tuning, inversion-of-control, etc. — and the challenges we faced along the way, providing guidance for other large-scale enterprise Flex projects.

For more information, put on your headphones and check out the Morgan Stanley Matrix micro-site. Some other resources are listed below. Hope to see you there!

Posted by tsugden at 9:40 PM | Comments (2)

September 4, 2009

Eliminate Common Bad Practices with FlexPMD

Adobe Technical Services are pleased to release FlexPMD to the community. FlexPMD is a new open-source tool for improving code quality. It works by analyzing ActionScript and MXML source files to identify common bad practices, like over-long classes or functions, reliance on magic strings, unused parameters, and many other programming mistakes or misjudgments. It can even spot code that might be causing performance problems, and furthermore, the ruleset can be customized and extended, to include rules specific to the coding conventions of your own project.

FlexPMD can be launched from the command line, but the best practice is to invoke it from your Ant or Maven continuous integration build scripts. In this case, a report will be generated each time a build is performed, describing the violations of your chosen ruleset. As soon as someone checks in their fancy new 1,000 line algorithm with nested loops, numeric variable names and a gaggle of change-watchers, the red flag will be raised. The report produced by Flex PMD allows simple coding mistakes to be identified and corrected immediately, when the cost is far cheaper than attempting to refactor a system that has been decaying for months.

FlexPMDReport.jpg

Figure 1: A Sample FlexPMD Report

Another benefit of FlexPMD is that code reviews become more valuable. Since FlexPMD can automatically identify the common problems, code reviewers are left to reflect on the deeper issues, like domain modeling, separation of concerns, proper encapsulation, and so on.

To find out more about FlexPMD and start using it on your own projects, follow these links to Adobe Open Source:

Credit goes to Xavier Agnetti for conceiving and leading this effort, with support and contributions from many in the Technical Services organization and other parts of Adobe.

Posted by tsugden at 7:21 AM | Comments (0)