Accessibility

Flex Article

 

Flex Application Performance: Tips and Techniques for Improving Client Application Performance

Brandon Purcell

 

Deepa Subramaniam

 

Macromedia Flex is a powerful platform that offers the ability to create Rich Internet Applications (RIAs). Misusing this power can result in areas of poor performance. Flex is like any other programming model because certain coding practices can be detrimental to the overall performance of your client application. This article describes some of the MXML coding practices that affect application performance on the client side and demonstrates simple techniques that will enhance the performance of your Flex application. More specifically, this article explores how to do the following tasks:

Note that the tips suggested in this article do not apply to all Flex applications. It is important to analyze the structure of your own application and modify the suggestions to tailor them to your needs. For ongoing coding and conceptual help, you can use the Flex support forums and Flex Developer Center.

Note also that this is the first part in a two-part article. The second part of this article, Flex Application Performance: Tips and Techniques for Improving Server-Side Performance, discusses the server-side enhancements and deployment options that you can use to improve the performance of your Flex application.

Requirements

To make the most of this article, you need the following:

Macromedia Flex

Learn more about Macromedia Flex.

Macromedia Flash Player 7

PDF Version of the Article


Feedback and Support

We have made every effort to ensure the accuracy of this article and all code included. Feedback for this article and all Flex performance issues is always appreciated. To submit feedback, please email us.

Detailed Table of Contents

 

Architecting Flex Applications That Perform Well

Ideally, performance is a topic that is in the back of your mind during every step of the development process—from application design to implementation and deployment. When creating a Flex application, think through the choice of containers and components that you use to ensure that the code is maintainable, organizationally clear, and performs well.

You can use the Flex navigator containers (Accordion, TabNavigator, and ViewStack) across all application types to organize content. The navigator containers organize content in a way that:

More specifically, Flex navigator containers help you organize content easily into different child views and control the creation of these views with deferred instantiation. Organizing content into these child views spreads out creation time for each child view because Flex creates a specific child view the first time a user requests that view. The "Navigator Containers Have Built-in Deferred Instantiation" section later in this article explains why Flex navigator containers perform better with deferred instantiation and how you can leverage deferred instantiation to make your application more robust.

Dashboard-style applications have also resulted in successful deployments. This type of application organizes content into modular, self-contained views that offer a more intuitive approach to application organization. Like the navigator containers, this approach performs well because it organizes complex views, with Flex creating them when the user drills down. Flex does not have to size, measure, and draw the views in the background, so it creates the selected view more quickly.

A Note About Flash Players

Before going into techniques for preventing common performance issues, ensure that you have installed Macromedia Flash Player 7 (7.0.14 or 7.0.19 or later). Flash Player is a multiple-platform client that lets users interact with Flash content. There are two types of players, the Flash Player release version and the Flash Debug Player version. The Flash Debug Player version is best used during the development phase, because it enables the Flex debugging and profiling features. Since most users use the release version of Flash Player, use this version to do performance tuning; running Flex applications with the Flash Debug Player version does not accurately represent the performance of your application. When running a SWF file, the Flash Debug Player version reports trace statements and warnings. This task requires ActionScript processing cycles that would otherwise resource a running application, which impacts the perceived application performance.

When you are ready to test application performance, verify you are running the application with Flash Player 7, the release version. Many Flex application developers make this simple mistake! To verify the version of Flash Player, run a Flex application in the browser you use during development, and then right-click inside the browser window. If you see a debug option in the context menu, you are running the Flash Debug Player version. If you fine-tune your application to perform well with the Flash Debug Player version, you can ensure that your application will perform the same, if not significantly better, with Flash Player 7.

For more on using the Flash Debug Player to debug client-side code, read Debugging Client-Side Code in Flex Applications.

Using Layouts, Hierarchy, and Containment Properly

The biggest Flex performance danger is yielding to the temptation to use containers randomly. Using too many containers dramatically reduces the performance of your application. This is the number one performance danger that Flex developers succumb to—and luckily it is 100 percent avoidable. The performance penalty occurs because Flex layout containers and their children follow sizing and measuring algorithms that determine x,y positions, preferred sizes, and styles. These calculations are resource-intensive; it is these calculations, coupled with Flash Player drawing complex objects, that cause a noticeable delay when starting a Flex application or when instantiating a new view in a navigator container. One principle dramatically speeds up application startup and interactivity time: Avoid unnecessary container nesting.

Avoid Nesting Containers Many Levels Deep

A good rule of thumb is to avoid excessive container nesting. At first, you might find it difficult to pinpoint superfluous container nesting. The following describes some of the more common cases of nesting containers and offers useful tips for choosing and using containers.

Below are a few examples of deeply nested code:

<mx:VBox>
  <mx:HBox>
    <mx:Form>
      <mx:FormItem>
       .....
       ...
      </mx:FormItem>
    </mx:Form>
  </mx:HBox>
</mx:VBox>

and

<mx:Grid>
  <mx:GridRow>
    <mx:GridItem>
      <mx:VBox>
       <mx:Button />
      </mx:VBox>
    </mx:GridItem>
  </mx:GridRow>
</mx:Grid>

When you nest containers, each container instance runs measuring and sizing algorithms on its children (some of which are containers themselves, so this measuring procedure can be recursive). When the layout algorithms have processed, and the relative layout values have been calculated, Flash Player draws the complex collection of objects comprising the view. By eliminating unnecessary work at object creation time, you give your application a boost and the performance benefits are readily apparent.

Typically, fewer containers provides good results with respect to creation time. If you find yourself nesting many levels deep, re-evaluate your choice of containers. Perhaps you can achieve the same layout with a different layout container in conjunction with style attributes, such as horizontal and vertical alignment, margins, spacers, and gaps. You can use margins and gaps to manipulate the space around controls and between the edge of controls and the edge of their parent containers. You can use spacer objects to fill unwanted space or to push controls around the screen. You can also align controls horizontally or vertically within their container. For example, take a look at the layout in Figure 1.

You can achieve this layout without using a Grid container.

Figure 1. You can achieve this layout without using a Grid container.

It is tempting to use a Grid container to achieve this layout:

<mx:Grid>
  <mx:GridRow>
    <mx:GridItem>
      <mx:Button label="Visa"/>
    </mx:GridItem>
    <mx:GridItem>
      <mx:Button label="MasterCard"/>
    </mx:GridItem>
    <mx:GridItem>
      <mx:Button label="Diner's Club"/>
    </mx:GridItem>
    <mx:GridItem>
      <mx:Button label="AmEx"/>
    </mx:GridItem>
  </mx:GridRow>
</mx:Grid>

However, this code is unnecessarily bloated. In fact, you can easily revise the code so that it looks exactly like Figure 1. The following snippet uses less code and results in a faster creation time and a slightly smaller SWF output.

<mx:HBox>
  <mx:Button label="Visa"/>
  <mx:Button label="MasterCard"/>
  <mx:Button label="Diner's Club"/>
  <mx:Button label="AmEx"/>
</mx:HBox>

Steven Webster, an active Flex community member, has an excellent entry in his blog on the dangers of nested containers, as well as tips on how to avoid nesting.

Absolute Positioning and Sizing

The Flex container classes are relative layout containers that arrange contents on the screen for you. However, the calculations to decipher how big each container and its children are, as well as where to place them, can potentially be resource-intensive. Here are two tips that can help reduce these calculations:

Use Grid Containers Wisely

Think of a Grid container as a layout choice already pushing the deep nesting rule. Grid, GridItem and GridRow are all containers in their own right, although GridItem and GridRow are only used in conjunction with the Grid container. You should only use a Grid container when your controls must line up both horizontally and vertically. Developers often gravitate to the Grid container, because they see the similarity to the HTML <table> tag. However, as a Flex developer, you can choose from multiple container choices to position objects (and some are less resource-intensive to use then others). This is not true of the HTML world, where <table> is really the only choice. The following code provides an example of when to use a Grid container—the controls in the different columns and rows must all line up (see Figure 2):

<mx:Grid>
 <mx:GridRow>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
 </mx:GridRow>
 <mx:GridRow>
  <mx:GridItem><mx:Button label="button"/></mx:GridItem>
  <mx:GridItem><mx:DateField /></mx:GridItem>
  <mx:GridItem><mx:Button label="button"/></mx:GridItem>
  <mx:GridItem><mx:DateField /></mx:GridItem>
 </mx:GridRow>
 <mx:GridRow>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
 </mx:GridRow>
</mx:Grid>
This UI is the perfect candidate for a Grid container.

(+) View Larger

Figure 2. This UI is the perfect candidate for a Grid container.

Some common misuses of Grid containers include the following:

As your Flex repertoire expands, you will see that there are alternate containers and controls that you can easily customize to meet your needs. For example, you can achieve the layout shown in Figure 4 with a List control and a custom cell renderer. You can use a cell renderer with any list-based component to create custom-formatted cells, and the cells can be different heights. The Flex documentation will have more information and examples on how to create a custom cell renderer. The performance of a List control with a custom cell renderer is spectacularly better than with a repeated Grid container. Or you can use the HorizontalList and TileList controls to create custom controls in an HBox or Tile-like layout. These controls perform very well because they only create elements visible in the initial view and then the user can scroll to see subsequent elements—instantiation time is quicker.

Examples of Common Container Redundancies to Avoid

The following list provides examples of common container redundancies to avoid:

Using Deferred Instantiation to Improve Perceived Performance

If the number one cause of performance problems is unnecessary measurement and layout from superfluous container nesting, the number two cause is creating objects before they are needed. To avoid this problem, you can use deferred instantiation. Flex uses deferred instantiation to determine which components to create at application startup. When using deferred instantiation, you can decide at which stages the user incurs the costs of component creation. Containers have a creationPolicy property that you set to specify when Flex should create the container (at startup, incrementally, when a user navigates to that container, or based on other user action).

The Flex navigator containers (ViewStack, Accordion, TabNavigator) have built-in deferred instantiation behavior. The default deferred instantiation behavior means that Flex does not create all the child views at startup, but only when a user triggers it by navigating to the container. The following code shows two navigator containers, TabNavigator and ViewStack, in use:

<mx:TabNavigator>
	<mx:VBox id="tabNavView1">
		 <mx:LinkBar dataProvider="myViewStack" />
		 <mx:ViewStack id="myViewStack">
			 <mx:VBox id="view1" >
				.
				.
				.
			 </mx:VBox>
			 <mx:VBox id="view2" >
				.
				.
				.
			 </mx:VBox>
			 <mx:VBox id="view3" >
				.
				.
				.
			 </mx:VBox>
		 </mx:ViewStack>
	</mx:VBox>
	<mx:VBox id="tabNavView2">
		 .
		 .
		 .
	</mx:VBox>
</mx:TabNavigator>

The TabNavigator container creates tabNavView1 because it is the first view displayed when Flex instantiates the TabNavigator container. Instantiating tabNavView1 will cause the LinkBar and the first view of the ViewStack, view1, to be instantiated. When the user interacts with the LinkBar to select another view in the ViewStack, Flex will create that view. Flex continues in this way, creating the navigator container descendants as it calls them.

The creationPolicy property on container tags control the creation of child views. The following list explains what each creationPolicy property does when set on Flex navigator containers:

By playing with the creationPolicy properties, you can manually handle the creation of child views and decide where in your application architecture you want to incur the cost of creating the child views of your navigator containers. Usability studies show that a better user experience is proffered when using the auto setting. A common mistake that can inadvertently slow your application startup time is to mistakenly set creationPolicy="all" on one of your navigator containers. Use creationPolicy="all" only if you are completely sure that the component creation plan you have in place is efficient and timely.

Progressive Layout—Queued Creation of Components

In the process of fine-tuning performance, you may reach a point where you have whittled your application's startup time to as fast as possible. However, this does not mean there are no more performance improvements you can make; you could choose to use progressive layout. Progressive layout is a UI concept that involves wiring your application to lay out components in a piece-by-piece fashion so there is a shorter initial delay before components begin appearing on the screen. Progressive layout is similar to the way HTML applications load content in succession in a client.

Progressive layout does not quantifiably reduce application startup time, but it significantly improves the perceived startup time. You implement progressive layout by using the queued creationPolicy in the deferred instantiation architecture of Flex. See the example below, which loads three panels in successive fashion.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" >

<mx:HBox>

<mx:Panel id="panel1" title="Panel 1" width="210" height="240" horizontalAlign="center" verticalAlign="middle" creationPolicy="queued" creationIndex="1">
	<mx:DataGrid width="190" height="95">
        <mx:dataProvider>
            <mx:Array>
                <mx:Object Artist="Death Cab for Cutie" />
                <mx:Object Artist="The Postal Service" />
            </mx:Array>
        </mx:dataProvider>
	</mx:DataGrid>
	<mx:DataGrid width="190" height="95">
        <mx:dataProvider>
            <mx:Array>
			 <mx:Object Album="Such Great Heights" />
			 <mx:Object Album="We Know the Facts" />
            </mx:Array>
        </mx:dataProvider>
	</mx:DataGrid>
</mx:Panel>

<mx:Panel id="panel2" title="Panel 2" width="210" height="240" horizontalAlign="center" verticalAlign="middle" creationPolicy="queued" creationIndex="2">
	<mx:List width="190" height="95">
        <mx:dataProvider>
            <mx:Array>
                <mx:String>one</mx:String>
                <mx:String>two</mx:String>
                <mx:String>three</mx:String>
                <mx:String>four</mx:String>
            </mx:Array>
        </mx:dataProvider>
    </mx:List>
    <mx:List width="190" height="95">
        <mx:dataProvider>
            <mx:Array>
                <mx:String>red</mx:String>
                <mx:String>green</mx:String>
                <mx:String>yellow</mx:String>
                <mx:String>blue</mx:String>
            </mx:Array>
        </mx:dataProvider>
    </mx:List>
</mx:Panel>
<mx:Panel id="panel3" title="Panel 3" width="210" height="240" horizontalAlign="center" verticalAlign="middle" creationPolicy="queued" creationIndex="3">
	<mx:Tree width="190" height="95">
			<mx:dataProvider>
				<mx:XML>
					<node label="File">
					<node label="Open"/>
					</node>
					<node label="Close">
					<node label="Help"/>
					</node>
				</mx:XML>
			</mx:dataProvider>
		</mx:Tree>
		<mx:TextArea width="190" height="95">
			<mx:text>The Macromedia Flex presentation server offers a familiar, standards-based programming framework and powerful set of components for creating a rich, responsive presentation tier for enterprise Rich Internet Applications (RIAs).</mx:text>
		</mx:TextArea>
</mx:Panel>
</mx:HBox>

</mx:Application>

Jason Szeto, a developer on the Flex team, has written an in-depth article on implementing progressive layout in Flex applications, including using progressive layout in data-driven applications:"Building Flex Applications with Progressive Layout."

Handling Large Data Sets

Sometimes your application may appear slow because it manages a large amount of data at once. Matt Chotin, a software engineer on the Flex team, has some excellent entries on data management that address this issue. He discusses how to incorporate paging, sorting, and improving perceived performance on his blog.

Playing Complex Effects Smoothly

You may notice that transition effects seem choppy, especially when your effect has a short duration applied to a large view. What defines choppy? For example, a Fade effect that fades in a few distinct alpha stages, instead of a smooth and seamless fade. Or a Zoom effect that zooms in a few distinct sizes, instead of a gradual and smooth Zoom. There are a few ways to tweak your transition effects to play in a smoother fashion. Try the following suggestions and see which work best to improve effects in your application:

Sometimes animations play in a choppy fashion because background processing occurs and interferes with the animation. You may notice this when you have an effect attached to a handler that populates controls from a web-service result, or when you have an effect accompanying the creation of a large view. The set of tags are a subclass of the Effect class (Fade, Move, Resize, WipeLeft, and so on) have a public property, suspendBackgroundProcessing. When it is true, it blocks all background processing like measurement and layout while the effect plays. The default is false. Macromedia suggests that you set this property to true for a smooth playing of effects. However, you must realize that when you switch on suspendBackgroundProcessing, your effect cannot be interrupted while playing. Because of this, there are a few cases where you should avoid using suspendBackgroundProcessing="true". One common use of effects is to play an effect while the application waits for a web-service result to return. After the web-service result returns, the result handler tries to interrupt and stop the effect. If suspendBackgroundProcessing is set to true, the result handler cannot interrupt the effect, and the effect plays continuously, hanging the application. Avoid using suspendBackgroundProcessing in these cases.

Achieving Great Performance with Runtime Styles

Runtime cascading styles are very powerful, but you should use them sparingly and in the correct context. Dynamically setting styles on an instance of an object means calling UIObject's setStyle() method. The setStyle() method is one of the most expensive calls in the Flex application model framework, because the call requires notifying all the children of the newly styled object to do another style lookup. The resulting tree of children that must be notified can be quite large.

A common mistake that impacts performance is overusing or unnecessarily using the setStyle() method. In general, you only need the setStyle() method when you want to change styles on existing objects. Do not use it when setting up styles for an object for the first time. Instead, set styles in an <mx:Style> block, as explicit style properties on the MXML tag, through an external CSS style sheet, or as global styles. It is important to initialize your objects with the correct style information, if you do not expect these styles to change while your program executes (whether it is your application, a new view in a navigator container, or a dynamically created component).

Some applications need to call the setStyle() method during the application or object instantiation. If this is the case, call the setStyle() method early in the instantiation phase to avoid unnecessary lookups. Early in the instantiation phase means setting styles from the component or application's initialize event, instead of the creationComplete or other event. By setting the styles as early as possible during initialization, you avoid unnecessary style notification and lookup.

Using Dynamically Repeating Controls for Better Performance

New in Flex 1.5 is the addition of the HorizontalList and TileList controls. You can use these controls for layouts that require dynamically repeating elements. They perform much better than layouts that used Repeaters. In fact, layouts created during the Flex 1.0 timeframe that used a Repeater may often be replaced by a combination of the HorizontalList or TileList controls and cell renderers for better performance.

Using the HorizontalList and TileList Controls

The HorizontalList and TileList controls are List controls that display data elements horizontally or in a tile layout, much like the HBox or Tile containers. Unlike the Repeater object, performance with these controls is determined by what is visible in the HorizontalList and TileList at that time. This behavior reduces instantiation time of the view significantly; a Repeater’s instantiation time will always be equal to or worse than the HorizontalList and TileList controls.

The HorizontalList and TileList controls usually contain a horizontal or vertical scroll bar, used to access all the items in the list. When a user scrolls, it triggers the creation of subsequent elements in the List. Thus, the user avoids creating all the possible elements at startup; they are created only when requested.

The HorizontalList and TileList controls perform much better than a Repeater object. In most cases it is a better choice to use them instead of a Repeater. However the Repeater control is still available in Flex; it is better to use the Repeater control to repeat simple elements. For example, it would make more sense to repeat a collection of RadioButton controls using a Repeater then a Horizontal or TileList control.

Improving a Repeater Object's Performance

There are a few things to think about if you need to improve your Repeater object's performance. First, if you are using containers as the child of the Repeater object, check whether using a HorizontalList or TileList control would be better. If that is not the case, ensure that the containers used as the children of the Repeater do not have unnecessary container nesting and are as trim as possible. If a single instance of the repeated view takes a noticeable time to instantiate, repeating makes it worse. As mentioned previously in this article, multiple Grid containers in a Repeater object do not perform well because Grid containers themselves are resource-intensive containers to instantiate. An alternative solution is to try a List control with a custom cell renderer or the HorizontalList or TileList controls.

You should also set the recycleChildren property to true to improve a Repeater object's performance. The recycleChildren property is a boolean value that, when set to true, binds new data items into existing Repeater children, incrementally creates new children if there are more data items, and destroys extra children that are no longer required.

When you set this property to false, the Repeater object recreates all the repeated objects when you swap dataProvider properties, sort, and so on, which causes a performance lag. The FlexStore sample application has an example of recycleChildren at play. When you load the application, notice the Sort by option under the product thumbnail view. This enables users to sort the product thumbnails based on name or price. The ordering of the Repeater object's dataProvider property is what changes, the thumbnail views do not. By setting the recycleChildren property to true, the Repeater object does not recreate each thumbnail view; it simply reshuffles the dataProvider property based on name or price.

The default value of the recycleChildren property is false to ensure that you do not leave stale state information in a repeated instance. For example, suppose you use a Repeater object to display photo images and each Image control has an associated NumericStepper control for how many prints you want to order. Some of the state information, such as the image, comes from the dataProvider property, while other state information, such as the print count, is set by user interaction. If you set the recycleChildren property to true and page through the photos by incrementing the Repeater object's startingIndex value, the Image controls bind to the new images, but the NumericStepper control maintains the old information! You should use recycleChildren="false" only if it is too cumbersome to reset the state information manually, or if you are confident that modifying your dataProvider property should not trigger a recreation of the Repeater object's children.

This may go without saying, but the recycleChildren property has no effect on a Repeater object's speed when the Repeater object loads the first time. The recycleChildren property only improves performance for subsequent Repeater occurrences. If you know that your Repeater object will only create children once, there is no need to use the recycleChildren property or worry about the stale state situation.

Improving Performance of Charting Components

Flex provides a very robust library of charting components that give you a two-dimensional visual representation of your data. These charting components follow the same guidelines as other Flex components, including the same performance drawbacks.

The Flex charts have been designed to perform well. All charts cache intermediary values in the transformation from data to screen, so that only the minimum amount of recalculation occurs in response to any change to the data or chart. The most expensive actions to perform in Flex charts is forcing a chart to redraw an axis, or forcing a chart to recalculate its labels. In fact, it is faster to resize a chart than to change its dataProvider (a change that requires a chart to potentially redraw an axis or recalculate labels). Below are further tips that you can use to improve the performance of your Flex charting components.

Performance Tuning and Profiling Your Own Flex Application

Test the performance of your application early and often. It is always best to identify problem areas early and resolve them in an iterative manner, rather then trying to shove performance enhancements into existing, poorly performing code at the end of your application development cycle. The following subsections investigate using Runtime Shared Libraries (RSLs) to improve performance, as well as describe two approaches to performance testing your Flex client: using the ActionScript profiler and using a code snippet that times application initialization. We also provide a handy solution to time component and data gestures using the ActionScript getTimer() method. (See also the "Load Testing Your Flex Application" section in the "Flex Application Performance: Tips and Techniques to Improving Flex Server Performance" article.)

Using Runtime Shared Libraries (RSLs)

You can shrink the size of your application's resulting SWF file by externalizing shared assets into standalone files that you can separately download and cache on the client. Multiple Flex applications can load these shared assets at runtime, but each client need only to download them once. These shared files are called Runtime Shared Libraries.

Flex projects that have multiple Flex applications downloaded to the client can leverage RSLs for better performance. More specifically, the time it takes to download a Flex application once the initial RSL has been downloaded is significantly reduced.

However, not all applications benefit from RSLs. The following are examples of Flex applications that might use RSLs for better performance:

Depending on the type of Flex project you are developing, RSLs may or may not offer a performance benefit. Roger Gonzalez, a developer on the Flex team, has a more in-depth article focused on RSLs: "Using Runtime Shared Libraries."

 

Using the ActionScript Profiler

The ActionScript profiler records the time Flash Player takes to perform tasks in ActionScript. Most commonly, you use the profiler to determine how long an ActionScript function or method takes to execute, how often it is called, and how much time is spent executing in its descendant. This helps identify which objects might be taking too long to initialize, or whether there are bottlenecks due to heavy graphics use or poor coding. However, running the profiler adds overhead to the application you are analyzing. This is because the profiler runs with the Flash Debug Player version, which is slower than the release version. Analyze the results returned with the profiler relative to each other, but do not take them as correct absolute times. Running an application in the release version of Flash Player will yield different results when compared to running the same application with the Flash Debug Player version. The Flex documentation has more information on how to install and run the ActionScript profiler. Macromedia Flex Evangelist Christophe Coenraets also has an excellent blog entry on optimizing application performance with the ActionScript profiler.

Calculating the Application Initialization Time

A more simple approach to performance profiling is to use code to gauge startup time. The following snippet times application initialization time (the time it takes the Application object to create, measure, lay out, and draw all of its children); it does not include the time to download the client SWF, or any of the server-side processing such as checking the Flash Player version, checking the SWF cache, and so on. The following example shows a sample Flex application that, when invoked in a browser, shows a simple form populated with controls, with the time it took to initialize and print a label.

<?xml version="1.0" encoding="iso-8859-1"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" creationComplete="doLater(this,'doneNow')">
<mx:Script><![CDATA[
var dp = [{food:"apple", type:"fruit", color:"red"}, {food:"potato", type:"vegetable", color:"brown"}, {food:"pear", type:"fruit", color:"green"},
	{food:"orange", type:"fruit", color:"orange"},{food:"spinach", type:"vegetable", color:"green"},{food:"beet", type:"vegetable", color:"red"}];
function doneNow()
{
	doLater(this, "reallyDoneNow");
}
function reallyDoneNow()
{
	timerLabel.text += getTimer() + " ms"
}
]]></mx:Script>
<mx:Form>
	<mx:FormHeading label="Sample Form" />
	<mx:FormItem label="List Control">
		<mx:List dataProvider="{dp}" labelField="food"/>
	</mx:FormItem>
	<mx:FormItem label="DataGrid control">
		<mx:DataGrid width="200" dataProvider="{dp}"/>
	</mx:FormItem>
	<mx:FormItem label="Date controls">
		<mx:DateChooser />
		<mx:DateField />
	</mx:FormItem>
	<mx:FormItem label="Load Time">
		<mx:Label id="timerLabel" fontSize="12" fontWeight="bold" text="The application initialized in "/>
	</mx:FormItem>
</mx:Form>
</mx:Application>

The first thing is to get a baseline reading of your application startup time. Ensure that you exit all other running applications, verify that you are using the release version of Flash Player, and run the application three times to get three initialization times. The average of these three times is your baseline reading. As you implement performance tuning, confirm that the startup time is indeed getting faster.

This code will also help you see which portion of your application is the slowest and identify whether you can speed it up. To try this, selectively remove parts of your application to see whether the single part's startup time is relative to the entire application's startup time. This iterative process highlights the problem areas of your application. For example, this methodology might show you that View B of your application loads in six seconds out of an overall startup time of twelve seconds. View B is a problem area for which you can drill down into and investigate performance alternatives. This process is simpler than setting up and using the ActionScript profiler, although it yields much less detailed information.

Using getTimer() To Time Component and Data Gestures

The getTimer() function is a very useful ActionScript function that returns the number of milliseconds since a Flex client application has been running in the browser. Attaching getTimer() calls to events enables you to time component and data gestures. Brandon Purcell, coauthor of this article and a support engineer at Macromedia, has a blog entry explaining how to time Flex data service calls using getTimer().

Feedback and Support

We have made every effort to ensure the accuracy of this article and all code included. Feedback regarding this article and all Flex performance issues is always appreciated.

About the authors

Brandon Purcell started at Macromedia/Allaire four years ago as a support engineer working with ColdFusion and JRun. He has worked with the Professional Services Group helping customers with their architecture planning, code reviews, customized training, load testing, and performance tuning. He has also worked on special projects including the clustering, load testing and deployment of the new macromedia.com website. During his tenure with Macromedia, he has supported ColdFusion, JRun, Flash Remoting, and has written white papers and articles on clustering and high availability with ColdFusion and JRun. Currently he is working as an escalation engineer for the Flex Server Support Organization. You can visit him at his website.

Deepa Subramaniam is a software engineer for the Flex SDK. Straight out of UC Berkeley (Go Bears!), with an undergraduate degree in computer science, she has been at Adobe (formerly Macromedia) since 2004 and is very excited to be working on all things Flex related.