Archive for April, 2011

Catching UncaughtError in Flex Modules

A common issue amongst those building Flex Applications that use Flex Modules is that the UncaughtError capability of Flash Player 10.1 does not work for Modules. This is due to the fact that Modules dereference the module SWF’s loaderInfo right away, in order to make unloading modules automatic. In other words, as soon as you dereference the last instance of classes in the module, the SWF can be garbage collected. If Flex did not dereference the loaderInfo, the developer would have to keep track of what instances of module classes have been created and whether they are still around, and only if they are all gone would you dereference the loaderInfo.

It turns out that the UncaughtError mechanism relies on having loaderInfo references so the module subsystem in currently incompatible with UncaughtErrors. The Flash Player engineers are testing out a fix where the main application becomes the fallback for any UncaughtErrors that have not been caught and cancelled. For now, though, I figured out a way to hook directly to the module’s loaderInfo and listen to UncaughtErrorEvents there. That will allow you to get UncaughtErrors from the module. The key is in the timing. By the time the ModuleEvent.READY fires, it is too late, the loaderInfo has been dereferenced and is null. During ProgressEvents, the loaderInfo may not be available. But fortunately, at the time of ModuleEvent.SETUP, you can grab the loaderInfo and listen for UncaughtErrorEvents.

Here are some relevant snippets of code. Let’s say you have an application with an UncaughtErrorEvent handler like this:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
layout="vertical"
initialize="init()">

<fx:Script>
<![CDATA[
import mx.events.ModuleEvent;

private function init():void
{
systemManager.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR,
uncaughtErrorHandler);
}

private function uncaughtErrorHandler(event:UncaughtErrorEvent):void
{
trace("caught uncaught error");
event.preventDefault();
}

]]>
</fx:Script>

<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

<mx:ModuleLoader id="moduleLoader" url="GEHFlexModule.swf" width="200" height="150" />
</mx:Application>

In this app, the uncaughtErrorHandler will get UncaughtErrors from every other point of the application except for the module loaded by the ModuleLoader. To get the UncaughtErrors from the module, all you have to do is add a ModuleEvent.SETUP event handler:


<mx:ModuleLoader id="moduleLoader" url="GEHFlexModule.swf" width="200" height="150" setup="setup(event)" />

and use the setup event to hook up the uncaughtErrorHandler to UncaughtErrors from the module.


private function setup(event:ModuleEvent):void
{
DisplayObject(event.module.factory).loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR,
uncaughtErrorHandler);
}

Hope that helps.

Migratory Foul: Performance Problems Migrating From Flex 3.x To Flex 4.x

Some folks migrating 3.x projects to 4.x have run into noticeable
performance degradation, especially if they are using the default skins that
ship with each SDK. This article attempts to explain why and propose
alternative implementations.

The main reason for the difference is that the the default skins/theme for
4.x is Spark and the default skins/theme for 3.x is Halo. Spark skins are
simply not as fast as the Halo skins. The Halo skins are written as highly
optimized ActionScript and are based on a lightweight Flex class called
ProgrammaticSkin. And partly because of those optimizations, the way you
would write or modify a skin for a MX Button could be drastically different
than the way you’d write a skin for MX DataGrid or MX ComboBox.

In Spark, we wanted a consistent approach to writing every skin. And we
wanted interoperability with the MX components. For reasons like that, the
Spark skins are based on a Skin class that in turn is based on UIComponent.
That instantly makes your skin heavier and slower than a Halo skin. Then,
we wanted every skin to be written in MXML so that the tools can more easily
understand the parts of the skin and assist in the modification and
development of a skin. Most folks know that MXML tends to be slower than
ActionScript, but we chose MXML to enable non-programming designers to be
involved in the skinning workflow without those designers having to worry
about mucking up a bunch of ActionScript code.

The cost per-skin of this extra weight is on the order of a few milliseconds
per skin, but it adds up. A recent test case was putting 250 checkboxes on
the screen. A somewhat unrealistic case since it is hard to cram 250
checkboxes on a screen and make it usable, but it took another 500ms in the
debugger player so the developer noticed right away when he went from 3.x
with Halo to 4.x with Spark. Even if the goal was 100 checkboxes, the extra
200ms would cause some animation to freeze noticeably.

Now, if you are migrating a 3.x project for which you have already written
your own custom theme based on ProgrammaticSkin and you are going to use the
same theme in 4.x, you shouldn’t see problems of this magnitude. It really
has only been an issue when you were using the Halo theme and you now try to
use an MXML-based theme like Spark. So what should you do? Consider not
using MXML-based themes for now. We are looking at ways to optimize an
MXML-based skin hopefully in time for our 2012 releases so hopefully this is
just a short-term issue. We must admit, though, that it is enough of an
issue that the mobile theme for the new mobile components in Flex 4.5 are
written in ActionScript and not in MXML, and that’s why we’re working on
MXML skin performance post-Flex 4.5.

You have choices: You can only swap in ActionScript-based skins for a few
components, or swap in a whole theme. Just replacing the Spark MXML
checkbox skin with the Halo checkbox skin (but leaving the Application and
other skins as MXML-based Spark skins) made a huge difference in performance
since the majority of work was in those 250 checkbox skins that were being
drawn.

Another new capability of Flex 4.x that can cause noticeable performance
degradation when compared to a 3.x application is what we call Advanced CSS.
In Flex 4 we support more CSS selector types but they require more
processing and less caching. If you create enough components in one chunk,
you might notice the extra time spent. We are looking at optimizations
post-Flex 4.5 as well. You can turn off Advanced CSS by setting the
compiler’s compatibility-version flag to 3, but that turns off lots of other
things as well and makes it harder to incrementally add or swap in Spark
components.

It is possible to subclass components and turn off Advanced CSS
for entire classes of components. The following link shows how I turned off
Advanced CSS in a subclass of CheckBox.
Download Sample Source

In analyzing these test cases, it became apparent that the “natural” way to
build up display object “trees” in ActionScript is not the most optimal in
terms of performance. Lots of folks dynamically create dialogs and other
sub-sections of their UI via code like this:


var loginUI:VBox = new VBox();
var loginText:TextInput = new TextInput();
loginUI.addChild(loginText);
var loginButton:Button = new Button();
loginUI.addChild(loginButton);
app.addChild(loginUI);

It turns out this is terribly inefficient compared to this almost identical
code:


var loginUI:VBox = new VBox();
app.addChild(loginUI);
var loginText:TextInput = new TextInput();
loginUI.addChild(loginText);
var loginButton:Button = new Button();
loginUI.addChild(loginButton);

All I did was addChild the outer container before adding its children. In
other words, it is faster to parent the parent before parenting the
children. Why? Because the CSS style calculations that involve inheriting
styles cannot be calculated until you have a parent. So in the first
example, when adding the TextInput and Button to the Vbox, a bunch of
temporary work gets done that gets tossed and re-done when the Vbox is
finally added to the child. If you use the second pattern, the CSS style
calculations don’t have to do any temporary, throw-away, work. It turns out
if you look at the code generated for an MXML file, you’ll see that parents
are parented before parenting their children. In the 250 checkbox cases,
the code was using the first pattern. By changing it to the second pattern
(and using the Halo theme) the test case on 4.x actually runs faster than
the 3.x test case. Yes, if the same optimization had been done on the 3.x
test case then 3.x would still be faster, but there is less degradation for
the second pattern because that is the common MXML-generated path and some
work was done to optimize it. Another new feature of 4.x is per-module
styles and the overhead of that capability (which had the main benefit of
greatly reducing probability that modules will get stuck in memory) carries
less penalty if you parent the parent first.

Remember that the underlying Flash Player is a deferred renderer. Adding an
empty Vbox to the app first won’t cause it to show up on the screen until
the rest of the code finishes running so there is no danger of flicker or
other visual artifacts.

In conclusion, if you are seeing performance degradation when migrating from
3.x to 4.x, and it is related to these topics in this article, then it was a
decided trade-off we made to involve designers in the development process
and produce better user experiences, or provide more CSS capabilities, or
reduce the chance memory leaks. But you can choose to use ActionScript
skins, do some subclassing to turn off Advanced CSS on components that are
created often, and build your dynamic UI more optimally and reduce the
degradation or in some cases, get even better performance than what you had
experienced in 3.x.