-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Firing run loop on mousemove unnecessary? #11540
Comments
It's only happening just in-case someone has a mouse related handler on one of the rendered components. If instead components informed the event dispatcher the events they need on render and no longer need on un render. We could remove this, instead only listening to exactly what is required. The mouse/touch events introduce an unfortunate cost, especially when they are not frequently used. |
Is there a way to infer this from the component, or would the component need to manually declare what is needs? If the latter, we'd need to choose the set of events that are listened for by default, and the set of events you need to manually opt in to. |
yes, https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/views/component.js#L223 is how one declares interest in an event from a component. |
So then we could just ref count this on component creation and the decrement on destruction, and then add and remove this listener as needed? |
I think this gets tricky with improved actions, because you can declare event handlers in the template.
You completely loose the ability to introspect the class. |
@chadhietala - In that scenario, you are not actually using the |
@rwjblue So it doesn't cause a runloop? Is this the same for the old |
@chadhietala - No, |
Yup it causes a run loop, but it's one that you want. Since you are absolutely invoking ember code. This is much better then all the preemptive handlers that run for. All mouse events regardless of if a handler is present. An interim step is actually to skip the run loop for events that don't find a handler. |
https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/system/event_dispatcher.js#L234-L242 could likely detect if the given view has such a handler, and only invoke the run-loop if it is about to enter user code. To handle bubbling correctly, it may need to be slightly more creative. This approach I believe will be the easiest, no ref counting needed. Sure we sill need to attach event listeners to everything, but we only bother invoking a run-loop if we truely are about to invoke code that requires it. I suspect this will cure the original concern which prompted this issue. |
So to make sure I understand this, the idea is to:
This sounds like it will address my issue. However, what is more expensive, traversing the view hierarchy looking for handlers, or executing a no-op run loop? |
We traverse it anyways |
jQuery fast paths event handling for many events, I think Ember should likely look into doing so too, in addition to any inquiry into using I'd put the overall cost on this as an extra .5-4ms / touchmove or mousemove event that's being used to manipulate position on screen (much of which depends on how many layers it needs to bubble through etc.). Not horrendous, but definitely expensive when lots of such events are involved. (Edit: that cost I peg above is a rough eyeball of the difference between using touchmove through Ember and using it as a direct handler on the component) |
I believe we are limited by our ie9 support and a true bubbling phase. Maybe not? Would love for someone to dive into this area an propose some improvements. Enumerating cost/benefit would also be handy |
IE9 allows for |
I've also got the resources/knowledge to do a decent cost/benefit run down, I'll see what I can whip up. |
Good thing we dropped ie8 for 2.0 |
Yep :) |
Anyone interesting in championing this? |
@runspired are you still looking into doing a cost/benefit run down? |
Yes. |
@runspired how would fastpathing component events in Ember work? Would there be a step on initiation where the tree was walked to identify any relevant listeners? |
More likely events should be moved back into an events hash, I'm not sure why they were moved out of one before. Once there, they can be auto registered on initialization, but that might require ember having knowledge of a component tree. There's trade offs there for sure. The quickest gain is useCapture. |
What does the events hash look like I'm es6 classes? @runspired I think most of core would love to see us switch to our own capture based delegation. But time is thing, are you interested to pushing forward an rfc? |
@stefanpenner I'm absolutely in favor of pushing forward an RFC, although I might (humbly) suggest pushing forward two RFCs. The first, to use The second, to convert to using |
As for the question on what this hash would look like with ES6 classes, I'm not sure I follow. Perhaps I don't know enough about the limitations/implementation of ES6 classes. |
Pardon my ignorance, but two questions:
+1 for the Pointer event, though it sounds like that might deserve it's own ticket. |
For info on PEP: https://github.com/jquery/PEP |
see: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener |
My motivation isn't as a performance advantage, but rather to enable more sanity when dealing with complex event scenarios. It may also have a positive perf side-affect. In addition, to today we actually can incur several re-entrant scenarios, causing perf/bugs because we blindly allow bubbling and delegation. I'm trying to finish up some tests for the memory leak @raytiley i'll try to post in more detail here later. |
I do think a sane first step might be to remove the use of the run loop until there's actual user code to execute (vs each bubble being a run loop call). |
This is partially already the case. But the bubble phase run.join should be moved into view.handleEvent likely https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/system/event_dispatcher.js#L241 |
Wouldn't run.join in dispatch event create a new loop if there weren't one? |
If we move this to We likely need to add if (view.hasOrAncestorHas(eventName)) {
Ember.run.join(... bubble ...);
} else {
// noop
} |
Yeah the |
I did some perf testing on TL;DR ~45% performance boost across the board. |
@rwjblue closed in favor of rfc/implementation? |
your commit doesn't fix the run loop join, only the ability to turn mousemove off |
Maybe we need to bundle up some of the talking points and push some work for capture phase + improved event dispatcher. Having vague hard to action issues is annoying. |
@stefanpenner I have a branch where I am working on this actually, I think it's been added to your Friday schedule as a talking point |
Awesome. Can you link it. Or submit a WIP for review? |
PR coming as soon as I finish off the walker. Will also be adding a second flag for resolution caching (e.g. from element to handler) so that repeated firing is super fast. |
@stefanpenner - It is also on our agenda for Friday. |
Sorry I was trying to reference this issue, not close it. |
Don't spin up extra run-loops when bubbling events. Fixes #11540
Looks like a new run loop is kicked off every time the mouse moves.
Is this really necessary? @stefanpenner suggested that we might instead have components opt-in to needing this, instead of assuming we need a run loop on mouse movement.
The text was updated successfully, but these errors were encountered: