Home  >  

Can Event Performance be improved in AS3?

Author photo
AddThis Social Bookmark Button

I came back from RIAdventure all stoked with new ideas to research and nail down in my own mind. One of the ideas I thought I heard there was the thought that you could probably improve performance by using Object Pooling to lower the overhead of Events used in Flash (and even more in Flex). At the heart of this concept is the idea that instantiating an Object is nearly always more expensive in terms of processor time than simply using one that was created earlier.

This idea was revolutionary for me, because every example I'd seen for using events showed code something like dispatchEvent(new Event('someEvent'));. So I set about trying to find out if you really could keep the same event around in memory and dispatch it at convenient moments. The first thing I did was do a search to see if anyone was using object pooling with Events in Flash or Flex. I came up with nothing. But I did find a comment on this post that implied that someone, at least, believed that it was possible to redispatch the same event.

So it seemed to me it was worth demonstrating this in an example file, which I have done. What you're looking at is a Flex 3 Application that has an instance of EventReusingComponent in it. EventReusingComponent has an instance of flash.events.Event and an instance of TestCustomEvent, which has an additional property, payload. Payload is just a string property that gets populated with whatever extra information we want. In this case, we're just going to put the number of times the "Dispatch Custom Event" button gets clicked.

As you can see, the first time you click this button, it shows "Custom event handled (payload=1)", and the second time you click it, you get "payload = 2", etc.

Uh, that's what it does, right? Right?

No. Instead, on the second and subsequent clicks, payload is an empty string. So what's happened? To find out, I started setting break points. I set one right before _customEvent is dispatched, to see that it is set up properly. I also set a break point in the first line of customHandler in the main MXML file, which is listening for a "custom" event coming from the EventReusingComponent.

Before the dispatchEvent line, the _customEvent event is configured properly–its payload property always contains a string with the number of times this button has been clicked in it. Yet in the event handler, the payload property is empty.

I remembered a comment I'd read in a discussion of what people know about Events that isn't necessarily documented, which suggests that the clone override gets called when an event gets manually dispatched. So I put a break point in there, and Bingo! I had my reason for why the payload was coming through empty. If you dispatch the same event twice, EventDispatcher somehow knows what you've done and creates a copy for redispatch.

This raised the question of whether I could simply use my clone() override to return the instance I was trying to redispatch. In a word, no. If you try that, the event simply doesn't get dispatched and dies without error.

So you cannot avoid the hit for object instantiation under the current implementation of EventDispatcher. Could you then write your own version of EventDispatcher, where this would work maybe? It looks like not. So, potentially this could be a viable design pattern under future versions of Flash, but for now, there is no way to avoid the creation of a new Event when you want to dispatch one. Even if you think you're reusing the same event, EventDispatcher is going behind your back and cloning your event, which creates a new Object.

In summary, this research was a big failure in terms of proving that you can reuse an event. But I think that even failed research teaches you something in the end. Thanks for reading.

Read more from Amy Blankenship. Amy Blankenship's Atom feed

Comments

11 Comments

TJ said:

Interesting read Amy, thank you for doing the research. I've often wondered this myself, as AS3 performance is critical when using Flex, IMO. Because we are already dealing with so many things the framework does for us, such as the component lifecycle and event management, that cannot be modified, I am constantly researching ways to improve the overall performance of my Flex apps.

Please keep us updated if make any discoveries with this!

Darren said:

I'm wondering what you mean by "overhead"? Do you mean memory or CPU cycles or both? I think both would have been negligible - events are short-lived and insignficant in CPU cycles compared to a visual component for example - but I agree it's good to try these experiments to see if some performance gains could be had.

An area where I often wonder whether performance could be improved is using the built-in Flex binding. In most examples you see the built-in binding mechanism used wherever a value needs to be updated when another changes. Surely making the watched value private and updating the dependent value in it's setter is far more efficient than going through the event creation/listening/bubbling/responding/destruction/etc. process to change a single value? What are your thoughts on this?

Darren said:

I'm wondering what you mean by "overhead"? Do you mean memory or CPU cycles or both? I think both would have been negligible - events are short-lived and insignficant in CPU cycles compared to a visual component for example - but I agree it's good to try these experiments to see if some performance gains could be had.

An area where I often wonder whether performance could be improved is using the built-in Flex binding. In most examples you see the built-in binding mechanism used wherever a value needs to be updated when another changes. Surely making the watched value private and updating the dependent value in it's setter is far more efficient than going through the event creation/listening/bubbling/responding/destruction/etc. process to change a single value? What are your thoughts on this?

James said:

When I click the second button, payload is nothing, is that a bug?

Amy Blankenship said:

Yes, Darren, I mean CPU cycles, or more accurately, frame rate.

You are correct that the primary issue in Flex is with data binding. Here is a presentation with some good ideas on how to minimize the overhead caused by data binding http://tv.adobe.com/watch/360flex-conference/diving-in-the-data-binding-waters-by-michael-labriola/ .

Another suggestion is to do something like this:

override public function dispatchEvent(evt:Event):Boolean {
if (hasEventListener()) {
return super. dispatchEvent(evt) {
}
return false;
}

That way, you're not dispatching events that no one cares about.

One thing I would not recommend is to ever set the properties in a child DisplayObject component in a setter, unless you've created all of the children in the constructor (which I also would not recommend).

This is because you can't be sure that the children exist when the setter is called, which will give you a null property exception. Instead, I'd recommend setting a flag in tandem with the private variable that indicates that the property has changed and call invalidateProperties(). Then in commitProperties(), check the flag and set whatever properties are appropriate.

If your class is a subclass of Halo Container , I'd further recommend that you override the createComponentsFromDescriptors() function to call invalidateProperties() and add a check in commitProperties() for processedDescriptors. See the "Handling Delayed Instantiation in Flex 3" that I wrote several weeks ago for more info.

Additionally, if you have something like a ViewStack where you're trying to set a property on one of the children of the second pane, you will also need jump through hoops to make sure it's instantiated before you address it or face a null pointer exception.

These types of problems are the reason why data binding is so popular: it swallows errors related to trying to read or set values on null objects.

DELL said:

Hi Amy/Darren,

You both are right. My concern is a developer must know how to use smart performance tips but more important is where to use. The end user must get what our best.

Jonathan Kaye said:

Dear Amy,

Thanks for trying. I ran into the issue previously using Flash (http://flashsim.wordpress.com/2009/08/06/dispatching-custom-event-in-handler-for-other-event-as3/) and I stuck my head in the sand pretending I was reusing something, when I secretly could see that cloning was happening whether I wanted it or not.

Adam said:

I fought with the same thing when migrating to AS3 and that was my rather painless solution. I’m not as technical as some other people and I try to make things as understandable as possible, but that seems to be working for me really well thus far.

hope that helps.

buoyancy aids

Todd said:

I am a little confused. Why would you want to track number of clicks or number of events fired? Wouldn't this be better handled by a view anyway? I mean Events are meant to simply track when an event happens. A single instance in time. The number of times that events is fired is tracked by the object doing the listening. At least that is how I always thought of it. Why would you want the event to track any data information. I think of data inside of Events as a transfer, like let me pass data from this class to that class and let the classes handle the information as a view.

Amy Blankenship said:

The payload property could contain anything, and was simply a means to demonstrate what happens when you use a custom event in this scenario. It's pretty common to need to pass more information than strictly what event has happened. For instance, you might have a "modelPropertyChanged" event where the payload is the name of the property that changed, or you might pass information about what choice was selected in a survey question.

The reason to attempt to dispatch the same event twice is simple: because creating any object, including an Event, takes more CPU cycles than using one you already have. I explained that in the article, but as Flex developers we already work in a world where we often don't think about small optimizations, so it bears repeating.

James said:

I would just *disable* the button after dispatch Event.

Leave a comment


Type the characters you see in the picture above.


Tag Cloud

Technical Speakers

Who is the best technical speaker you have seen?

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.