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.

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

  1. Hi Alex great article

    But something I’ve been wondering a lot about, is how come it be that MXML are slower then Actionscript code? Because I always thought that MXML got translated into the same swf bytecode as actionscript and at runtime that wouldn’t make any difference?

    Best Regards
    Martin

    • Alex Harui says:

      Use the -keep-generated-actionscript option to see what kind of ActionScript is generated from MXML. You will probably see heavier base classes, more binding logic, and even more properties used to hold references to child tags. That’s because MXML has certain contracts it has to uphold that pure ActionScript doesn’t, like support binding and having GraphicalElement children.

  2. Hi Alex,

    “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.”

    short-term issue? What should we do in the meantime?

    I am working on a huge Flash/Flex finance application and we are not able to switch to a new version every 12 months.
    That’s probably fine for small form based applications but not for a long-term module based application.

    Based on our experience we think that the current Flex versions should be used only if it’s really necessary!
    In most of the cases pure Flash is a much better choice. Not only in terms of performance, but also in terms of maintenance and control.

    I really hope that Adobe will investigate this topic and will provide us a framework which facilitates developing fast, extensible and sustainable applications.

    Regards
    Hannes

    • Alex Harui says:

      If you are using 3.x and are happy with it, I’d stay on it. We’ve been saying that 3.x is fine for existing projects. 4.x is the recommended choice for new projects or significant new work, especially if you are putting together a whole new UI and want to get designers involved via Catalyst or FXG importing. It may not run as fast as a 3.x project, but if you aren’t creating lots of UI objects you should be able to get to a better end result sooner because the designers were involved early and could use the same skinning workflow everywhere.

      Frameworks do have a cost. Pure ActionScript projects do run fastest, but can take longer to write and maintain since you have to do everything yourself. The MX framework traded off consistency for speed, which often happens when trying to optimize things.

  3. hi alex,
    thanks for the interesting article.
    you described a really weak point in the framework about styles and display object tree:
    if the user has to care and to know about implementation details about how the styles are applied there is a problem in the API design. if it is not used correctly it can result in code which is “terribly inefficient” – the misuse should to be hidden from the developer by the framework. If it is not possible to solve this issue inside of the framework (for instance with an additional lifecycle phase where styles are applied after all components are parented) then it should at least be emphasised in developers guidelines. i am doing many years now flex but i never was aware of this issue, so probably wasted a lot of performance for nothing…
    in general i think adobe should take much more care about performance issues. otherwise flex has no good future for large scale applications. to serve the needs of designers and rapid delevopment projects is valid but it seems that it produce a lot of penalties for projects where performance and (end)user experience is more important then a quick and easy development process. in my experience the quick and easy way is also only successful for small projects. if it gets larger the intransparency (for instance mxml bindings) costs more effort and time in bugfixing as it has saved initially.

    • Alex Harui says:

      I agree it should have been better documented. It wasn’t until I started digging that we saw how big the difference had grown to become. It was smaller in the 2.x days, but with new features and bug fixes it has grown to be significant.

      Believe me, performance is important. We are constantly looking for ways to make the framework perform better.

  4. Jack Viers says:

    Alex,

    I understand the cost per skin should be on the order of “a few milliseconds”. This was my expectation as well. The results are much more than “a few milliseconds.”

    My test case for the bug you closed on JIRA was much more succinct and real-world than 250 checkboxes on a screen. The first test case simply put one of each type of spark element and one each type of mx element in two separate applications. MX was compiled using the 3.5 mxmlc, and Spark was compiled with the 4.1 mxmlc.

    Each application consisted of exactly 25 components, constructed in MXML at authortime. The MX button, which, as you point out uses ProgrammatticSkin instead of UIComponent, rendered in 402 milliseconds, which is slow enough already. The Spark Button rendered in 994 milliseconds. Note that this is 2.47x the render time of the flex3 component, at 592 milliseconds slower. This is on an application with 25 other components, which is not beyond the scope of a real-world use-case.

    In addition, you’ll notice that I used MXML to create the page at authortime…which means that I followed your second pattern of parenting containers before parenting the children.

    Advanced CSS selector engines are slow. In that you are correct. But if the Adobe team had looked around there are plenty of examples of optimized css selector engines to choose from in both the open-source browser community and the many JS libraries out there that support cascading inheritance/pseudo-selectors. If you want a pure ActionScript implementation that I assume could also be ported directly to optimized ABC or implemented in-player you might want to take a look at the Sizzle JS selector engine as a possible project to port and modify.

    As I’ve stated in the bug on JIRA, a few milliseconds per component is a fine tradeoff for the new SOC pattern of component development. However, 592 milliseconds is not “a few milliseconds,” it is a HALF a second. Please take a closer look at how to optimize this. Contact me at my email, I have a few ideas on how to fix the issue, but do not have access to the source code of the particular classes to ascertain wether or not they will actually work.

    • Alex Harui says:

      Are you referring to SDK-29904? That bug is not closed.

      The primary focus of this investigation was a bit more “apples-vs-apples”. IOW, what is the penalty when migrating from 3.x to 4.x using MX components? I didn’t spend much time on MX vs Spark like you did because Spark is a different architecture with more features like a consistent skinning workflow, TLF instead of TextField, support for GraphicalElements, etc. It isn’t expected to match MX speeds.

      The numbers quoted in the post are release SWFs on a production player. Debug SWFs on a debugger player are slower still. What configuration did you use for your numbers? How did you determine the portion of time attributable to the skins?

      Flex CSS isn’t quite the standard so it isn’t clear we can use the JS engines. Our current implementation does leave lots of room for improvement though.

      Flex is fully open source. All the files I can touch are available to you.

  5. Ridwan Bejamin says:

    In the article you wrote that you can “You can only swap in ActionScript-based skins for a few
    components”. How to actually go about doing that, say how do I just specify combo box to use Halo theme and the rest of application still use the Spark theme

    Thanks

  6. mcallinan says:

    Alex,

    We are in the process of moving an Enterprise app from 3.5 to 4.1, and have hit several speed bumps along the way. In addition to the parenting order performance differences you mention, we also hit another style related performance issue that we just came across a possible solution for. It’s documented on Taylor Brown’s site here: http://taytay.com/?p=169. When we use his patch to StyleProtoChain.as, we see a 2x speed up in our application, bringing it back to SDK 3.5 performance levels. We have 500+ style declarations distributed throughout several css files, so that may be why this fix doubles our performance also.

    I’m curious if Adobe is aware of this issue already, and if so when a fix is planned for release? Please tell us it will be in the 4.5 release! We’re leary about including this patch in our product since the solution isn’t sanctioned by Adobe, and we don’t know what side affects it may have on our product. But we also can’t release our app in its current state. The performance degration from 3.5 to 4.1 is just too great.

  7. Andrei Kouzmenkov says:

    Folks, please check http://forums.adobe.com/message/3648094#3648094
    It looks like the major performance problem with CSS in SDK 4 has been isolated and a quick dirty fix proposed, which seems to work.
    I get 50% reduction in initialization of our heavily styled Flex MX app.
    Still the SDK 4.1 version of our code is 1.5-2 times slower than SDK 3.5, but that’s already a huge improvement.

    Many thanks to YNAB!

  8. Pingback: A simple monkey patch to double Flex 4 instantiation performance | Taytay.com