Optimizing Adobe Flash for Performance
Total Page:16
File Type:pdf, Size:1020Kb
Optimizing Adobe Flash for Performance by Keith Gladstien In this article, you'll find strategies to optimize performance of applications made with Flash Professional. The process of optimization involves editing your FLA project files to ensure that the published application's realized (or actual) frame rate is sufficient to make animations play back fluidly. If you've ever run a Flash project and seen stuttering animation, that is the behavior you want to avoid. If you'd like to replicate a test with stuttering animation, create a project with a simple animation and assign a frame rate less than 10 (such as 5). When you test the movie by publishing the SWF file, you'll see an example of stuttering animation. There are two main components that determine Flash performance: CPU/GPU usage and memory usage. These components are not independent of each other. Some optimization adjustments applied to improve one aspect will have a negative impact on the other. In the sections below, I'll explain how that works and provide reasons why you might judiciously decide to, for example, increase memory use in order to decrease the CPU/GPU load. If you develop Flash games for mobile devices, it's likely you'll need to use some of the techniques discussed below to achieve acceptable frame rates. If you are creating non-game apps for the desktop, it's possible to achieve acceptable frame rates with little or no familiarity with the techniques described in this article. Judging and measuring game performance with Adobe Scout The only way to accurately judge the performance of your app is to run it on the target platform – your development platform can have very different performance characteristics, especially if you're developing for mobile devices. In late 2012, Adobe released a new tool called Adobe Scout (formerly known as "Project Monocle") that lets you do just this. Scout is a profiler and performance debugging tool for Flash content. It lets you accurately measure the performance of your app – its frame rate, CPU utilization, memory use, rendering performance, and much more. It supports remote profiling, meaning that you can profile your app while it's running on a mobile device. This lets you tune the performance of your app for the specific platform you're targeting. You can download Scout from here. For more information about what Scout can do, and how to use it, you can read the getting started guide. Memory tracking, memory use, and performance testing Scout can help you to detect memory leaks in your content, but version 1.0 doesn't show you which objects are in memory and causing the leak. More detailed memory features are planned for future releases, coming soon. In the meantime, if you discover memory issues on the target platform, you can use the MT class to debug your app and resolve issues. (In the provided sample files folder, open the ActionScript class located in this directory: MT/com/kglad/MT.as.) The code in the MT class is adapted from code provided by Damian Connolly on his site divillysausages.com. The MT class reports frame rate, memory consumption, and lists any objects that are still in memory. To use the MT class, follow these steps: 1. Import the MT class: import com.kglad.MT; 2. Initialize it from the document class or the project's main timeline with this line: MT.init(this,reportFrequency); In the line above, the this keyword references the movie's main Timeline and reportFrequency is an integer. The main Timeline reference is used to compute the realized frame rate and reportFrequency is the frequency (in seconds) that the trace output reports the frame rate and amount of memory consumed by a Flash application. If you don't want to output periodic frame rate and memory reporting data, pass 0 (or anything less). Even if you choose not to output the frame rate, you can still use the memory tracker part of this class. 3. To track objects you create in your app, add this line: MT.track(whatever_object,any_detail); In this line of code, the first parameter is the object you want to track (to see if it is removed from memory) and the second parameter is an optional string containing anything you want to test. (Developers typically use this parameter to get details about what, where, and/or when you started tracking a specific object). 4. To create a report that reveals whether your tracked objects still exist in memory, add this line: MT.report(); It is not necessary that you understand the MT class to use it. However, it is a good idea to check out how the Dictionary class is used to store weak references to all the objects passed to MT.track(). The class includes extensive comments that describe how it works. Many of the sample file tests provided at the beginning of this article use the MT class. To learn more about working with the MT class, check out the tests to see how the MT class is used. Similar to the observer effect in physics, the mere fact that we are measuring the frame rate and/or memory and/or tracking memory, changes the frame rate and memory utilization of your app. However, the effect of measurement can be minimized if the trace output is relatively infrequent. Additionally, the absolute numbers are usually not important. It is the change in frame rate and/or memory use over time that is important for debugging and optimization. The MT class does a good job of reporting these types of changes. The MT class does not allow trace outputs more than once per second to help minimize spuriously low frame rate reports caused by frequent use of the trace method. (The trace method itself can slow the frame rate.) It's important to note that you can always eliminate trace output as a confounder of frame rate determination by using a textfield instead of trace output, if desired. The MT class is the only tool used by the sample file test projects to check memory usage and pinpoint memory problems. It also indirectly measures CPU/GPU usage (by checking the actual frame rate of the executing app). Implementing optimization techniques In the sections below, I'll begin by discussing memory management guidelines, with sub-topics listed in alphabetical order. Next, I'll provide information on CPU/GPU management with sub- topics related to that goal. It may seem logical to provide the techniques in two sections. However, as you read through this article, remember that memory management affects CPU/GPU usage, so the recommendations listed in the memory management section work in tandem with the tips listed in the CPU/GPU section. Before providing the specific best practices you can use, I think it is also helpful to include information about the techniques so that you can learn which are the easiest or hardest to implement. I'll also provide a second list that prioritizes the techniques from greatest to least benefit. Keep in mind that these lists are subjective. The order depends on personal developer experience and capabilities, as well as the test situation and test environment. Easiest to hardest optimization techniques to implement 1. Do not use filters. 2. Always use reverse for-loops. Avoid writing do-loops and while-loops. 3. Explicitly stop Timers to ready them for garbage collection. 4. Use weak event listeners and remove listeners when no longer needed. 5. Strictly type variables whenever possible. 6. Explicitly disable mouse interactivity when mouse interactivity is not required. 7. Replace dispatchEvents with callback functions whenever possible. 8. Stop Sounds to enable garbage collection for Sounds and SoundChannels. 9. Use the most basic DisplayObject needed for each element. 10. Always use cacheAsBitmap and cacheAsBitmapMatrix with air apps (mobile devices). 11. Reuse Objects whenever possible. 12. Event.ENTER_FRAME loops: Use different listeners and different listener functions applied to as few DisplayObjects as possible. 13. Pool Objects instead of creating and garbage collecting Objects. 14. Use partial blitting. 15. Use stage blitting. 16. Use Stage3D. Greatest to least benefit of optimization techniques 1. Use stage blitting (if there is enough system memory). 2. Use Stage3D. 3. Use partial blitting. 4. Use cacheAsBitmap and cacheAsBitmapMatrix with mobile devices. 5. Explicitly disable mouse interactivity when mouse interactivity not needed. 6. Do not use filters. 7. Use the most basic DisplayObject needed. 8. Reuse Objects whenever possible. 9. Event.ENTER_FRAME loops: Use different listeners and different listener functions applied to as few DisplayObjects as possible. 10. Use reverse for-loops. Avoid writing do-loops and while-loops. 11. Pool Objects instead of creating and garbage collecting Objects. 12. Strictly type variables whenever possible. 13. Use weak event listeners and remove listeners. 14. Replace dispatchEvents with callback functions whenever possible. 15. Explicitly stop Timers to prepare them for garbage collection. 16. Stop Sounds to enable garbage collection for Sounds and SoundChannels. With these priorities in mind, proceed to the next section to learn how to update your Flash projects to manage memory more efficiently. Managing memory The list of suggestions below is not exhaustive but it contains strategies that can significantly improve the performance of Flash content. Using a callback function vs. dispatchEvent There is an increase in memory use when dispatching events because each event must be created and memory is allocated to it. That behavior makes sense: events are objects and therefore require memory. I tested a handful of events and found each consumed 40 to 128 bytes. I also discovered that using callback functions used less memory and ran more efficiently than using events.