Performance tips for AIR application development

by Retired ‎12-20-2012 01:44 PM - edited ‎12-21-2012 09:45 AM (9,819 Views)

Note: There is no perfect rendering method. Choosing the right one depends on what you are doing with your application and experimentation with your content.

 

Movie quality

When developing an Adobe® AIR® application lowering the stage quality can help improve performance. BlackBerry® 10 phones have a high DPI so a lower stage quality will be harder to detect for users.

 

StageQuality.LOW: Favors playback speed over appearance and does not use anti-aliasing. Lower quality vector shapes. Never anti-alias, never smooth bitmaps.

 

StageQuality.MEDIUM: Applies some anti-aliasing but does not smooth scaled bitmaps. This setting is the default value for AIR on mobile devices.

 

StageQuality.HIGH: (Default on the desktop) Favors appearance over playback speed and always uses anti-aliasing. If the SWF file does not contain animation, scaled bitmaps are smoothed; if the SWF file contains animation, bitmaps are not smoothed.

 

StageQuality.BEST: Provides the best display quality and does not consider playback speed. All output is anti-aliased and scaled bitmaps are always smoothed.

 

Rendering Optimization

Certain features are heavy:

  • Bitmap effects (shadow, gloss, emboss…)
  • Masks (inherently vector-based)
  • Alpha channels
  • Blend modes (add, multiply…)
  • Embedded fonts (Especially Unicode)
  • Complex vector artwork

It is best to use vector artwork sparingly when you want to optimize performance. Vectors are displayed through a process of mathematical calculations performed for every line/polygon in each and every frame. For example, math calculations are processed 60 times a second if the stage fps is set to 60. The more complex the vector graphic is, the more complex the math equations will be.

 

Redraw Regions

Every time objects move in an AIR application they consume CPU resources. As demonstrated in the graphic any objects that are animated will be redrawn in a rectangle region. The redraw region is the part of the display list that is consuming CPU resources. The more redraw regions and the larger they are the more CPU resources are needed.

 

To improve performance, try to keep what your application is drawing to the display list limited. Everything in the redraw region is getting redrawn every frame so try to keep a shallow display list. One thing to note is that hidden objects will still take CPU resources. Set the visible property of hidden running objects to false or remove them from the display list altogether. These steps ensure that the display object is frozen and uses minimal CPU power.

 

redraw.png

 

 

Render Modes

There are 4 render modes that can be selected when you create an AIR application using

 

<renderMode>mode</renderMode> in the application.xml file.

 

<renderMode>cpu</renderMode> or <renderMode>auto</renderMode> (Using Auto defaults to CPU)

  • Everything is rendered in software
  • Easiest to build
  • Performance improvements can be made with bitmap caching

<renderMode>gpu</renderMode>

  • Vectors and cached surfaces are rendered through hardware
  • Text and vectors can use cacheAsBitmapMatrix
  • There are many limitations
    • The Adobe® Flex® framework does not support the GPU rendering mode.
    • Filters are not supported
    • PixelBender blends, and fills are not supported
    • The following blend modes are not supported: layer, alpha, erase, overlay, hardlight, lighten, and darken
    • Using GPU rendering mode in an app that plays video is not recommended.
    • In GPU rendering mode, text fields are not properly moved to a visible location when the virtual keyboard opens. To ensure that your text field is visible while the user enters text use the softKeyboardRect property of the stage and soft keyboard events to move the text field to the visible area.
    • If a display object cannot be rendered by the GPU, it is not displayed at all. For example, if a filter is applied to a display object, the object is not shown.

<renderMode>direct</renderMode> (Stage3D – Coming soon)

  • GPU accelerated rendering engine
  • Faster than any other rendering technique
  • Many useful frameworks such as Starling and Away3D
  • Create applications close to native level performance
  • Handle most recurring scripts in Event.ENTER_FRAME

 

Bitmap caching

Bitmap caching allows complex vector assets to be rasterized once instead of every frame. This technique works great for things like complex gradients or text.

 

myObject.cacheAsBitmap = true;

 

You should note that turning on cacheAsBitmap for an animated object such as a movie clip that has its timeline playing, you’ll get the opposite result. You can move this object by the x,y coordinates freely but if you try to scale, rotate, or add alpha effects the bitmap will need to be redrawn which will impact performance.

 

If you’re using the GPU rendering mode you can use the cacheAsBitmapMatrix property.

 

myObject.cacheAsBitmapMatrix = new Matrix();

 

By using the cacheAsBitmapMatrix property, you can rotate, scale, skew, and change the alpha value of a display object without triggering bitmap regeneration.

 

You can also use the BitmapData class to create a custom bitmap caching behavior. For example if we have a container that has a bunch of graphics, different text fields in it etc. and would like to animate it we could convert it to a bitmap, animate the bitmap, and then show the container again in it’s final position. To do that you could pass the container to this function:

 

public static function getBitmap(obj:DisplayObject, w:Number, h:Number):Bitmap
{
    var bitmapData&colon;BitmapData = new BitmapData(w, h, true, 0xFFFFFFFF);
    bitmapData.draw(obj);
    return new Bitmap(bitmapData);
}

 

We could then animate the container and then remove it by doing the following:

 

private function removeBitmap(bitmap:Bitmap):void
{
    removeChild(bitmap);
    bitmap.bitmapData.dispose();
    bitmap = null;
}

 

Tweening engine

For animation/tweening I recommend using Actuate. It makes animating much easier and is very fast. http://code.google.com/p/actuate

 

 

Blitting

Blitting is usually used when creating a game. It refers to putting a bitmap object on the stage for your game area and manually drawing contents into it with BitmapData.copyPixels().

  • Can be very fast in certain cases
  • Makes use of sprite sheets
  • You must manage your own rendering, caching etc.
  • Does not scale up very well

 

Performance tips

  • Keep the display list as flat as possible
  • Just say no to using filters
  • Test early and often on actual devices
  • Use profiling tools to find bottlenecks
  • Pooling and reuse makes garbage collection fire less frequently
  • Tell Flash when to trigger garbage collection
  • XML can slow things down
  • Callbacks are faster than events
  • Type everything

 

FAQ

Q: Why doesn’t my app perform as well on BlackBerry 10 as it does on the BlackBerry® PlayBook™?

 

A: The primary reason is that the processor has to render more pixels to the screen. The BlackBerry 10 has a resolution of 1280x768 vs. the PlayBook’s 1024x600.

 

Q: Is there a way to improve FPS when scrolling a list?

 

A: The first thing you will want to do is set opaqueBackground on your cellRenderers. If you have a custom cell renderer set it in the init method of your subclass. Try to avoid any transparencies in your cells at all costs. You will see a significant increase here.

 

You can also turn it on globally for all of the default renderers fairly easily by injecting some CSS.

 

if( ThemeGlobals.currentTheme == ThemeGlobals.WHITE )
{
    ThemeGlobals.injectCSS( "CellRenderer { opaqueBackground:#FAFAFA };" );
}
else
{
    ThemeGlobals.injectCSS( "CellRenderer { opaqueBackground:#121212 };" );
}

 

By turning this on this list now runs around 40fps pretty consistently. It's a pretty big jump for 1 line code change.

 

Caching intersecting objects

list.png

 

Although you can't see it because they are masked, when the list scrolls it actually intersects with the items below and above it. In this specific instance the list will intersect with the action bar below it, as well as the 2 check boxes and title bar above it. Because the renderer is not smart enough to understand that it is masked, any object that it intersects, that is not cached, will cause a re-draw. What you want to do is make sure you set the following on any objects that might intersect it.

 

enable_cb.cacheAsBitmap = true;
enable_cb.cacheAsBitmapMatrix = new Matrix();

 

Setting those 2 properties on the 3 items above and 1 below makes the list run between 50-55fps.

 

And if you set opaqueBackground on the 2 check boxes it starts to run at 55-58fps. There are shadows under the title bar and above the action bar so you can't set opaqueBackground there in most cases.

 

You can even take it further and set opaqueBackground on the Container that the controls are in, as well as the main view. This will also give you a little bit of a boost.

 

Summary

As you can see with just a few lines of code you can take your list from 20fps to just under 60fps. All of these stats came from swiping down in the left corner on the homescreen of the device to bring up the red stats. These numbers are all averages as well.

 

Other tips

 

mouseChildren = false

If your renderers don't have any interactive objects inside of it, it is highly recommended that you set mouseChildren = false in your cell renderer. This will increase performance when pressing on cells to select them as well as scrolling. You can set this globally in your app by using the following code at the beginning of your app.

 

ThemeGlobals.injectCSS( "CellRenderer { mouseChildren:false };" );

 

 

More information and resources

Rendering performance – Tips and tricks from Adobe

 

GPU rendering mode limitations – You’ll find a list of all of the GPU rendering mode limitations here.

 

60FPS or Bust! – A presentation from Andy Hall of Adobe that outlines some important performance techniques.

 

Optimizing performance for the Adobe Flash Platform – Adobes official documentation for rendering performance techniques.