Hey, Daniel! As you know, removeEventListener() creates a copy of the Vector.<Function> that contains every listener for a certain event type. This is to ensure that events currently being dispatched will reach all listeners that were added at the time of the dispatchEvent() call. Removing a listener should only affect future dispatchEvent() calls.
I don't think it's necessary to create a duplicate Vector.<Function> every time that removeEventListener() is called, though. If an event is not currently being dispatched, there should be no risk from modifying the original Vector.<Function> directly.
My proposed optimization is to keep a stack of event types currently being dispatched. If the event type passed to removeEventListener() is in the stack, Starling will create a duplicate Vector.<Function>, just like it does today. If the event type is not in the stack, no duplicate is created and the original Vector.<Function> is modified directly.
I've included a screenshot of the Deallocations view in Scout. I was running the Feathers Components Explorer example, and I simply navigated back and forth between the main menu screen and a screen containing a GroupedList component several times.
The top half of the screenshot shows Starling's current behavior where a duplicate Vector.<Function> is created every time. The bottom half shows my modified version of EventDispatcher that modifies the original Vector.<Function>, if possible.
As you can see, Vector.<Function> started out as the second most deallocated object in my test. After my modifications, less than half the number of Vector.<Function> instances were deallocated, and it dropped below Array to third place.
A very simple and elegant solution that helps avoid the issue with this method. Thanks a lot for the pull request, Josh! I merged it right away. :smile:
Hey, Daniel! As you know, removeEventListener() creates a copy of the Vector.<Function> that contains every listener for a certain event type. This is to ensure that events currently being dispatched will reach all listeners that were added at the time of the dispatchEvent() call. Removing a listener should only affect future dispatchEvent() calls.
I don't think it's necessary to create a duplicate Vector.<Function> every time that removeEventListener() is called, though. If an event is not currently being dispatched, there should be no risk from modifying the original Vector.<Function> directly.
My proposed optimization is to keep a stack of event types currently being dispatched. If the event type passed to removeEventListener() is in the stack, Starling will create a duplicate Vector.<Function>, just like it does today. If the event type is not in the stack, no duplicate is created and the original Vector.<Function> is modified directly.
I've included a screenshot of the Deallocations view in Scout. I was running the Feathers Components Explorer example, and I simply navigated back and forth between the main menu screen and a screen containing a GroupedList component several times.
The top half of the screenshot shows Starling's current behavior where a duplicate Vector.<Function> is created every time. The bottom half shows my modified version of EventDispatcher that modifies the original Vector.<Function>, if possible.
As you can see, Vector.<Function> started out as the second most deallocated object in my test. After my modifications, less than half the number of Vector.<Function> instances were deallocated, and it dropped below Array to third place.