1) Why do we use Flex Profiling?
To find memory Leaks
To find excessive Allocation
to find long running process
to find excessively called process
2) Flex profiler doesnt report everything like
Doesnt Report Browser Memory
Doesnt Report Os Memory.
Memory used to display visuals
memory used to get events
memory used to handle network file access.
Memory used by the flash player
memory used by jit buffer.
Memory used by subobjects or strings.
3) System.total memory doesnt report everything either like
4) Whats new Flexbuilder4 Profiler
Improved object reference panel
shortest path from object to GC.
Viewing information in the Live Objects view
The Live Objects view displays information about the classes that the current application uses. This view shows which classes are instantiated, how many were created, how many are in memory, and how much memory the active objects are taking up.
The profiler updates the data in the Live Objects view continually while you profile the application. You do not have to refresh the view or keep focus on it to update the data.
The following table describes the columns in the Live Objects view:
Class : The classes that have instances in the currently running application.
Package :The package that each class is in. If the class is not in a package, then the value of this field is the file name that the class is in. The number following the dollar sign is a unique ID for that class.
If the Package field is empty, the class is in the global package or the unnamed package.
Cumulative Instances : The total number of instances of each class that have been created since the application started.
The number of instances of each class that are currently in memory. This value is always smaller than or equal to the value in the Cumulative Instances column.
Cumulative Memory :The total amount of memory, in bytes, that all instances of each class used, including classes that are no longer in memory.
Memory :The total amount of memory, in bytes, that all instances of each class currently use. This value is always smaller than or equal to the value in the Cumulative Memory column.
Using the Memory Snapshot view
The Memory Snapshot view displays information about the application’s objects and memory usage at a particular time. Unlike the Live Objects view, the data in the Memory Snapshot view is not continually updated
Using the Object References view
The Object References view displays stack traces for classes that were instantiated in the application.
To open the Object References view, double-click a class name in the Memory Snapshot or Loitering Objects views. The Object References view displays information about the selected class’s instances.
The Object References view displays data in two tables: the Instances table and the Allocation Trace table.
Performance profiling: is the process of looking for methods in your application that run slowly and can be improved. Once identified, these hot spots can be optimized to speed up execution times so that your application runs faster and responds more quickly to user interaction. You generally look for two things when doing performance profiling: a method that is called only once but takes more time to run than similar methods, or a method that may not take much time to run but is called many times. You use the performance profiling data to identify the methods that you then optimize. You might find that reducing the number of calls to a method is more effective than refactoring the code within the method.
Memory profiling : is the process of examining how much memory each object or type of object is using in the application. You use the memory profiling data in several ways: to see if there are objects that are larger than necessary, to see if there are too many objects of a single type, and to identify objects that are not garbage collected (memory leaks). By using the memory profiling data, you can try to reduce the size of objects, reduce the number of objects that are created, or allow objects to be garbage collected by removing references to them.
Memory profiling can slow performance of your application because it uses much more memory than performance profiling. You should only do memory profiling when necessary.
Using the Allocation Trace view
The Allocation Trace view shows which methods were called between two memory snapshots and how much memory was consumed during those method calls. To open the Allocation Trace view, you select two memory snapshots, and then click the View Allocation Trace button. For information on recording a memory snapshot.
The result of the memory snapshot comparison is a list of methods that Flash Player executed between the two memory snapshots. For each of these methods, the profiler reports the number of objects created in that method.
Using the Object Statistics view
The Object Statistics view shows the performance statistics of the selected group of objects. This view helps you identify which methods call a disproportionate number of other methods. It also shows you how much memory the objects instantiated in those method calls consume. You use the Object Statistics view to identify potential memory leaks and other sources of performance problems in your application.
Using the Performance Profile view
The Performance Profile view is the primary view to use when doing performance profiling. It shows statistics such as number of calls, self-time, and cumulative time for the methods that are called during a particular sampling interval. You use this data to identify performance bottlenecks.
Changing timeout length
When you test your application, be aware of the scriptTimeLimit property. If an application takes too long to initialize, Flash Player warns users that a script is causing Flash Player to run slowly and prompts the user to abort the application. If this is the situation, you can set the scriptTimeLimit property of the tag to a longer time so that the Flex application has enough time to initialize.
However, the default value of the scriptTimeLimit property is 60 seconds, which is also the maximum, so you can only increase the value if you have previously set it to a lower value. You rarely need to change this value.
The following example sets the scriptTimeLimit property to 30:
Flex Memory and GarbageCollector
When you use addEventListener() method and register a event listener to an object you create reference. By default any object that has a reference to a listener will keep that reference until it is removed using the removeEventListener() method. Strong references will not be cleaned up by Flash player GC and remain in memory until the application is closed or the world ends, whichever comes first. This makes for a horribly leaky AIR applications,
The ActionScript 3.0 garbage collector uses two methods for locating objects with no active references: reference counting and mark sweeping.
Reference counting : Reference Counting is quite good and easy with no overhead on CPU,But it has the problem with circular references So in over to eradicate this sort of situations there is another approach Mark and Sweep.
How to identify memory leaks in Flex Application
Use Additional Parameters of Listener
The addEventListener() method does have some additional (and seldom used) parameters to create a weak reference when adding the listener to an object. On of those parameters is “useWeakReference”, the 5th parameter of the method. To utilize this parameter you need to set it from false to true:
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean= false);
var button:Button = new Button()
button.addEventListener(MouseEvent.click, handleMouseClick, false, 0, true);
Preventing client-side caching
When you test performance, ensure that you are not serving files from the local cache to Flash Player. Otherwise, this can give false results about download times. Also, during development and testing, you might want to change aspects of the application such as embedded images, but the browser continues to use the old images from your cache.
If the date and time in the If-Modified-Since request header matches the date and time in the Last-Modified response header, the browser loads the SWF file from its cache. Then the server returns the 304 Not Modified message. If the Last-Modified header is more recent, the server returns the SWF file.
You can use the following techniques to disable client-side caching:
Delete the Flex files from the browser’s cache after each interaction with your application. Browsers typically store the SWF file and other remote assets in their cache. On Microsoft Internet Explorer in Windows XP, for example, you can delete all the files in c:\Documents and Settings\username\Local Settings\Temporary Internet Files to force a refresh of the files on the next request.
Set the HTTP headers for the SWF file request in the HTML wrapper to prevent caching of the SWF file on the client. The following example shows how to set headers that prevent caching in JSP:
// Set Cache-Control to no-cache.
// Prevent proxy caching.
// Set expiration date to a date in the past.
response.setDateHeader(“Expires”, 946080000000L); //Approx Jan 1, 2000
// Force always modified.
response.header(“Last-Modified”, new Date());
Reducing SWF file sizes
You can improve initial user experience by reducing the time it takes to start an application. Part of this time is determined by the download process, where the SWF file is returned from the server to the client. The smaller the SWF file, the shorter the download wait. In addition, reducing the size of the SWF file also results in a shorter application initialization time. Larger SWF files take longer to unpack in Flash Player.
The mxmlc compiler includes several options that can help reduce SWF file size.
Using the bytecode optimizer
The bytecode optimizer can reduce the size of the Flex application’s SWF file by using bytecode merging and peephole optimization. Peephole optimization removes redundant instructions from the bytecode.
If you are using Flex Builder or the mxmlc command-line compiler, you can set the optimize compiler option to true, as the following example shows:
mxmlc -optimize=true MyApp.mxml
Disabling debugging can make your SWF files smaller. When debugging is enabled, the Flex compilers include line numbers and other navigational information in the SWF file that are only used in a debugging environment. Disabling debugging reduces functionality of the fdb command-line debugger and the debugger built into Flex Builder.
To disable debugging, set the debug compiler option to false. The default value for the mxmlc compiler is false. The default value for the compc compiler is true.
For more information about debugging, see Using the Command-Line Debugger.
Using strict mode
When you set the strict compiler option to true, the compiler verifies that definitions and package names in import statements are used in the application. If the imported classes are not used, the compiler reports an error.
There are various methods of externalizing assets used by your Flex applications; these include:
Using run-time stylesheets
Using Runtime Shared Libraries (RSLs)
Loading assets at run time rather than embedding them
Component libraries are SWC files that contain one or more components that are used by applications. SWC files also contain the namespace information that describe the contents of the SWC file. For more information about component libraries, see About SWC files.
Run-time shared libraries (RSLs).
RSLs are external shared assets that can be separately downloaded and cached on the client. These shared assets are loaded by any number of applications at run time. For more information on RSLs, see Using Runtime Shared Libraries.
Themes are a combination of graphical and programmatic skins, and Cascading Style Sheets (CSS). You use themes to define the look and feel of a Flex application.
Comparing dynamic and static linking
Most large applications use libraries of ActionScript classes and components. You must decide whether to use static or dynamic linking when using these libraries in your Flex applications.
When you use static linking, the compiler includes all components, classes, and their dependencies in the application SWF file when you compile the application. The result is a larger SWF file that takes longer to download but loads and runs quickly because all the code is in the SWF file. To compile your application that uses libraries and to statically link those definitions into your application, you use the library-path and include-libraries options to specify the locations of SWC files.
Dynamic linking is when some classes used by an application are left in an external file that is loaded at run time. The result is a smaller SWF file size for the main application, but the application relies on external files that are loaded during run time.
To dynamically link classes and components, you compile a library. You then instruct the compiler to exclude that library’s contents from the application SWF file. You must still provide link-checking at compile time even though the classes are not going to be included in the final SWF file.
You use dynamic linking by creating component libraries and compiling them with your application by using the external-library-path, externs, or load-externs compiler options. These options instruct the compiler to exclude resources defined by their arguments from inclusion in the application, but to check links against them and prepare to load them at run time. The external-library-path option specifies SWC files or directories for dynamic linking.
Using RSLs to reduce SWF file size
One way to reduce the size of your application’s SWF file is by externalizing shared assets into stand-alone files that can be separately downloaded and cached on the client. These shared assets are loaded by any number of applications at run time, but must be transferred only once to the client. These shared files are known as Runtime Shared Libraries (RSLs).
If you have multiple applications but those applications share a core set of components or classes, your users will be required to download those assets only once as an RSL. The applications that share the assets in the RSL use the same cached RSL as the source for the libraries as long as they are in the same domain. The resulting file size for your applications can be reduced. The benefits increase as the number of applications that use the RSL increases.
When you create an RSL, be sure to optimize it prior to deployment. This removes debugging information as well as unnecessary metadata from the RSL, which can dramatically reduce its size.
You use styles to define the look and feel of your Flex applications. You can use them to change the appearance of a single component, or apply them globally. Be aware that some methods of applying styles are more expensive than others. You can increase your application’s performance by changing the way you apply styles.
For more information about using styles, see Using Styles and Themes in the Adobe Flex 3 Developer Guide.
Loading stylesheets at run time
You can load stylesheets at run time by using the StyleManager. These style sheets take the form of SWF files that are dynamically loaded while your Flex application runs.
By loading style sheets at run time, you can load images (for graphical skins), fonts, type and class selectors, and programmatic skins into your Flex application without embedding them at compile time. This lets skins and fonts be partitioned into separate SWF files, away from the main application. As a result, the application’s SWF file size is smaller, which reduces the initial download time. However, the first time a run-time style sheet is used, it takes longer for the styles and skins to be applied because Flex must download the necessary CSS-based SWF file.
For more information, see the Adobe Flex 3 Developer Guide.
Reducing calls to the setStyle() method
Run-time cascading styles are very powerful, but use them sparingly and in the correct context. Calling the setStyle() method can be an expensive operation because the call requires notifying all the children of the newly-styled object. The resulting tree of children that must be notified can be quite large.
Using deferred creation
To improve the start-up time of your application, minimize the number of objects that are created when the application is first loaded. If a user-interface component is not initially visible at start up, create that component only when you need it. This is called deferred creation. Containers that have multiple views, such as an Accordion, provide built-in support for this behavior. You can use ActionScript to customize the creation order of multiple-view containers or defer the creation of other containers and controls.
To use deferred creation, you set the value of a component’s creationPolicy property to all, auto, or none.
Flex memory tuning tips
1. Memory Leaks caused by Event Listeners
Always remove unused event listeners. Each time an event listener is added to an object, it increases the object’s reference count. So the reference remains, until the event listener is removed. If for some reason, you cannot remove the event listener use the useWeakReference parameter in the addEventListener. This does not increase the reference count.
When you call addEventListener() on the TextInput instance, it responds by adding a reference to the object (the one that contains the handleTextChanged method) to a list of objects that need to be notified when this event occurs. When it’s time to broadcast the change event, the TextInput instance loops through this list and notifies each object that registered as a listener. In terms of garbage collection, this means that, in certain circumstances, if an object is listening for events it may never be available for garbage collection.
The following example shows a simple case:
var textInput:TextInput = new TextInput();
When adding an event listener to a broadcaster, the developer can specify that the event listener should use weak references. This is accomplished by specifying extra parameters for the addEventListener() method:
var textInput:TextInput = new TextInput();
textInput.addEventListener(‘change’, handleTextChanged, false, 0, true);
2. Using Item Renderer
Use item renderers judiciously. An item renderer derived from a Container class comes with lot of unnecessary overhead. Instead use a simpler class, may be an Actionscript class derived from a UIComponent. This would reduce a lot of overhead.
3. Using Images
Use images that are smaller in size and when they are large in number prefer not to embed them in the application. As far as the image formats are concerned, PNG images are much faster than other image types.
Use BitmapData as much as possible. Use dispose() method of BitmapData to free memory that is used to store the BitmapData object.
Use Binding only when necessary. Data binding expressions usually take up memory. Prefer assignments to Binding whenever possible.
Accessing local variables is much faster. If you have variables that need to be accessed more use local variables as they are stored on the stack and accessing them is much faster.
You could help the garbage collector by assigning unused variables to null.
6. Instance Creation
For components use deferred instantiation. This would immensly reduce the startup time. Be wary of creationPolicy=”all”. Try to avoid removeChild() / addChild() when it would work just as well to reuse an object or just toggle the visible property.
Minimize the use of containers. Try not to nest HBoxes within VBoxes and so on. Nested containers make up to huge overheads.
8. Types Conversions
Use types for the variables. Avoid implicit type conversions and when unsure of the type use the “as” operator.
Repeaters have a property called recycleChildren.Set it to true. When set to true, the repeater reuses the children it already created instead of creating new ones.
Use weak references in the Dictionary object.
Don’t unnecessarily load/unload modules. If you need to unload a module, make sure to remove all references pointing to it. In particular if you have an event listener from within the module to something outside the module, that can prevent the module’s memory from being reclaimed.
After making a NativeWindow you must call close() before it can be GC’ed. But you must remove references before you can call close(). Also when you open a FileStream object in asynchronous mode, pending event listeners can prevent the FileStream object from being GC’ed.
2. Flex Performance Profiling
Performance profiling is used to find aspects of the flex application that are unresponsive, or where performance can be improved. When profiling for performance, generally one should be looking for methods that are executed very frequently, or methods that take a long time whenever they’re executed. The combination of those two factors usually provides a good indication of where your time should be spent in optimizing or potentially refactoring.
Using the Flex Builder 3 Profiler, one can identify the slowest portions of the application and optimize it. Flex Builder profiler allows one to take performance snapshots to record how long was spent in each function. This is useful to identify the areas of code that might benefit from optimization. While profiler is running everything is much slower. Often Mouse or similar Events will seem to take lots of time, you can ignore these. Investigate your own functions and see if they have been called too often or they take too long.
Flex Performance Tuning Tips
Flex Speed Tips: Matt chotin has shared a some great tips to improve Flex performance. Following are a few of them:
* If you have a type in AS3, which you are not sure of always use the As operator to cast the type before you use it. This avoids VM errors with try/catch, which slow the execution and is ten times slower than the As operator.
* Array is access is slow if the array is sparse. It may be faster to put nulls in empty values as this speeds things up. Array misses are very slow, up to 20 times slower than finding a valid entry.
* Avoid implicit type conversion. In the player it will convert integers to numbers and back when asked to add integers. You might as well use numbers for everything and convert back to integer at the end.
* Local variable access is faster, so assign variables to local if they are accessed a lot. They will be stored on the stack and access is much quicker.
* Data Binding expressions take up memory and can slow down the application startup. It may be more efficient to do an assignment in code rather than using binding.
* Find a slow computer and run your application. If it runs OK ship it! Other wise you can use flash.utils.getTimer():int to get a time value in miliseconds before and after some process to time it.
More information on tuning ActionScript can be found in Matt chotin’s article