After a number of weeks hacking away at a mobile port of drink maestro in anticipation of the Air for Android release, I’ve learned a few lessons regarding flash performance on mobile that are worth sharing.
lesson #1: alpha is bad news
If you’re like me, you may use alpha to transition from one screen to the next, or to introduce new elements to the stage. I’ve never encountered much of an issue on the desktop with using alpha, even going back 10 years. On mobile flash, however, use of alpha will kill the framerate cold. It’s best just the avoid alpha completely if you can, and find a different way altogether.
lesson #2: GPU acceleration may not help matters
GPU acceleration is not a silver bullet, and in my case actually ended up significantly reducing the application’s frame rate. I was under the assumption I could tune the code up in CPU default/auto rendering, switch on GPU rendering and expect a boost. This was not a safe assumption. After researching a bit, it’s clear that GPU rendering is fantastic for compositing bitmaps, but that is about as far as it goes. At the very least, try both rendering options with an fps counter in place for validation of the better option for your application. EDIT: The default (auto) rendering is some form of black box that may delegate some tasks to the GPU, I’d assumed the default was CPU.
lesson #3: defer some rendering on user input if response time is lagging
On an event such as a mouse click, there’s a lot you can do on a desktop without the interface showing any sign of slowing down. On a mobile device, if you try to do anything too complex, the application’s response time is going to drop through the floor. When a user taps the screen, it’s important to give them a sign that the input was captured, quickly. The easiest way I’ve found to manage this is to split the rendering, painting something to the screen to signal the user the tap/click was captured, and deferring some of the render with a timer (therefore picking it up on the next frame). While this may create an html-like feel as the visual elements load over two frames, the user isn’t going to be left confused and frustrated.
lesson #4: background process any cpu intensive rendering
Drink maestro had a list of cocktails 175 entries long that need to be rendered. On the desktop this would render in the blink of an eye, on mobile it takes a second or two. Such an operation needs to build a rendering queue and divide the processing across many enter frame events, otherwise the interface will freeze until the processing is complete. This can be done by capturing time, and exiting a render-queued while loop after a set number of milliseconds has passed. Google “pseudo-threading” for more information.
lesson #5: use bitmap data when tweening
Tweening even mildly complex vector data can slow the frame rate to unacceptable levels. In this case, acceptable performance can be attained by drawing a clip to bitmap (BitmapData.draw()) and swapping the bitmap in place of the vector before tweening it. If you clip contains interactive elements, just swap the clip back when the tween completes (assuming it can deactivate during movement). “cacheAsBitmap” may also work here, but I’ve become a little superstitious of its use lately having seen some memory consumption weirdness – bitmapdata gives the the ability to explicitly dispose() of the data when you’re finished.
lesson #6: the height and width properties can be a bottleneck
Again, not something you’d worry about on the desktop – but getting the height and width of a complex clip is not instantaneous. The getter needs to actually look at the contents and recalculate on every reference. If you use width and height values of any element more than once in a function, put it into a variable so that the getters aren’t getting fired on every reference. On significantly complex clips, you may even want to store the values and only update when you know the clip has been altered. Cache invalidation can be a real pain in the butt, so before going that far – trace some timings and validate that height and width references are the source of a slowdown.
lesson #7: develop on the device
As you work through any mobile development with flash, your best bet is to develop on an actual mobile device. If you develop on the device you’re targeting, performance issues should be obvious the moment you test your code. I ended up in the unenviable position of porting from the desktop to mobile – it was definitely the wrong direction to be going, it would be far easier to port mobile to the desktop.
There’s certainly more I could add, but these nuggets of information are at the top of my list. I should note that optimizing through caching, background processing, bitmap swapping, etc.. is not going to make life easier. Quite the contrary, but if responsiveness and/or frame rate are not at the levels you’d like, the tips above should help.
Adobe has posted their own set of guidelines for optimizing for mobile here.