Archive › April, 2011

A simple monkey patch to double Flex 4 instantiation performance

(That headline is a bit of hyperbole, but it was true for our project!)
UPDATE: According to Andrei (see comment below), this fix also halved the startup time of their app! Time to try to add some more keywords to this article in hopes that more folks will stop by and give this a shot: Flex 4 slow vs Flex 3. How to speed up Flex 4. Flex 4 performance. Also, Alex Harui recently posted on his blog about Flex 4 performance issues, and he mentions that their StyleProtoChain can be slow, and provides an alternate way of getting perf back. I haven’t tested his method though. If you do, I’d love to hear how it compares. And now on with the article…

We are in the process of upgrading our AIR app, You Need a Budget, to use Flex 4. We’re basically trying to change as little as possible, but we need to use Flex 4 for a new library of code we purchased. That means we’re still using our old MX controls, and we’re using the Halo theme. However, we quickly discovered a major performance bottleneck. Our app was taking at least twice as long to load as it did before. So, I loaded up the debugger and randomly started breaking into the code. Virtually every time I broke into the code, I was in the same darn function:
[code light="true"]StyleProtoChain::matchStyleDeclarations[/code]

For every component being instantiated, Flex was doing a linear search through all of our styles and asking each of them, “Do you apply to this component being instantiated?” We have a stylesheet with about 300 declarations in it, so that meant that Flex was making 300 queries per object instantiated. In short, it was slow.

So, I monkey-patched to make it cache these style lookups. No more linear searches! My fix is quick and dirty, so there are scenarios where the styles could get changed out from under the cache. Although it appears to work great for us, I can imagine lots of scenarios where it will break, so your mileage may vary. Still, my guess is that you’ll see a tremendous speed improvement. Our load times went down by more than half. Any time I can get performance increases like this with so little code, I want to share it with the world.

This is a monkey patch of Flex 4.1, so I don’t know how/if it will work for Flex 4.0 or 4.5. To find my changes look for the “//TB” comments or anything related to the matchUniversalStyleDeclarations function I added.

If you’ve never monkey patched Flex before, just drop this file into your project in an “mx/styles” folder. Do a full rebuild, and I believe you’ll be good to go. You might have to reference StyleProtoChain elsewhere in your project to guarantee it gets compiled in, but I don’t recall.

Comments ( 5 )

Be careful how you “cast” Error objects in AS3!

I was doing some testing of my crash reporting class I wrote for our AIR app. The getStackTrace method I was calling on the error object though was completely wrong. Here is the code I had:

[code lang="as3"]
protected static function getExtraReportInfo(error : Object, userEmail : String, userDescription : String) : String
var stackTrace : String;
if (error is Error)
stackTrace = Error(error).getStackTrace();


That was always returning the stack trace of the getExtraReportInfo function! It was NOT returning the stack trace of the error when it was thrown! I then tried this line of code instead, and it worked:

[code lang="as3"]
stackTrace = (error as Error).getStackTrace();

The reason it worked is that the Error(error) is not actually a cast. I believe it’s constructing a new Error instance based on the error object I’m passing in. The second example above IS a real cast, so I got the results I was expecting.

I wish casting syntax was not the same as construction syntax. Then we could avoid these sorts of bugs. I don’t normally do these sorts of inline casts anyway, but here is my working code now:

[code lang="as3"]
protected static function getExtraReportInfo(errorObj : Object, userEmail : String, userDescription : String) : String
var stackTrace : String = "";
var castError : Error = errorObj as Error;

if (castError != null)
stackTrace = castError.getStackTrace();


Comments ( 1 )

Moving a revision/changeset/patch from SVN to Mercurial

When I converted our SVN repository to Mercurial (Kiln), I left out some of our branches. Last night I wanted to get them ported back over to our Mercurial repository, and here’s how I did it:

  1. Browsed the old SVN repository using Tortoise SVN.
  2. Went to “View Log” for the branch I wanted to port over.
  3. In the log, I selected the first revision of the branch (where it was branched from trunk), and the last revision of the branch.
  4. Right-clicked, and clicked “View difference as unified diff”
  5. Copied the text that appeared and pasted it in a file called: branchPatch.txt
  6. Noted the date that I had originally made the branch in SVN. Let’s call it SVN Change # 500, on June 8, 2010
  7. In Mercurial, viewed history to find the corresponding changeset in Mercurial for SVN Change #500 on June 8th. Let’s call it revision #100
  8. Updated to that revision:
    [code lang="as3"]hg up 100
  9. Made a branch:
    [code lang="as3"]hg branch OldBranches/MyBranchName
    hg commit -m "Creating a branch"[/code]
  10. Imported the patch:
    [code lang="as3"]hg import -p 0 --no-commit ../branchPatch.txt

    -p 0 tells it to use a “strip count” of 0. Otherwise, when applying the patch from SVN, it will try to strip the first part of the path off when finding files it needs to modify. You’ll get error messages that it couldn’t apply the patch.
    –no-commit makes the changes to your working folder instead of submitting each of the changes separately. Without this, my first attempt gave me 12 separate revisions in Mercurial, one for each file I modified.
  11. Commit the changes:
    [code lang="as3"]hg commit -m "Now Oldbranches/MyBranchName has been moved over from SVN"

Warning: This does not preserve full history of the branch. Your corresponding branch in mercurial will contain the final state of the branch in SVN, but it will not contain the intermediate revisions to get you there. I didn’t care in my case because my branches were small and only had a few revisions leading up to their final state.

Comments ( 0 )