-
-
Notifications
You must be signed in to change notification settings - Fork 925
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
Optimize events, support objects with handleEvent
#1949
Conversation
- `handleEvent` is a very useful tool. - Always use `addEventListener`/`removeEventListener`, since it's required for this optimization. - Change log updated. - Drive-by: make DOM mock work with both event listener types. - Drive-by: eliminate possibility of `Object.prototype` interference.
- `handleEvent` is checked on dispatch, like in the DOM. - Had to reorder attribute key checking so `undefined` events still got removed. - Drive-by: Optimize the initial attribute key checking a little. - Drive-by: Fix changelog v2.0.0 link in TOC.
o(spy.callCount).equals(0) | ||
}) | ||
|
||
o("removes event added via addEventListener when null", function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these tests may be redundant if everything is added with addEventListener
unless you want to test MouseEvents and TouchEvents.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather stay safe, in case someone down the road decides it's a good idea to start using the raw properties again. That way, we're less likely to see regressions.
Putting some 👀 on perf. Changes look fine otherwise. |
@tivac I didn't post my results here, but I did run the suite. It was a mild improvement in speed (and made it more consistent), but that wasn't the primary focus of the optimization - it was to reduce memory/GC pressure. |
Weird, I was seeing on the order of 1-5% slower perf. I got lost in the weeds some on making some tooling around comparing perf of branches easier though. |
@tivac That's odd...I was seeing that in gain, so I guess we can assume it's within the margin of error. I'll note a pretty important detail: adding/removing event listeners is much more expensive in browsers than with our mock. Did you run the benchmarks in an actual browser or just Node? (I'd expect that if you're benching based on the mock, you should get a mild slowdown due to a slightly increased overhead.) Another item of note: it no longer fast-paths things like |
Using the Either way, the diff was pretty sketchy due to not recording them in the old vnode. |
@spacejack It's actually almost as cheap as normal property assignment in practice to modify the |
Ah, yeah that explains it. If it's faster in browsers than I'm fine w/ this. |
@tivac Hold off on the merge until I get a better diagnosis on why I'm getting inconsistent perf benchmarks in the browser. I also need to do a proper memory profile check to verify that. I'll come back once I've got results (and potential fixes). |
To clarify, the inconsistency is just wider variance in speed. (And it's slightly slower, but I'm going to look into the diff a little bit to see what happened.) |
Re-ordered the type checks so that I can avoid polymorphic property lookups in event updates. (It improved the common case of no change by a little over ~40%.)
Okay...so here's some numbers, from benchmarking in Chrome: Before this patch:
After this patch:
I'll come back with memory numbers later. |
From running the memory profiler (to create a timeline), it appears that the memory usage is slightly increased (1.3MB to 1.4MB over 25s or about ~25KB to ~28KB per sample) in the faster benchmark due to more strings being retained. So my memory claims are invalid (at least for 1-2 listeners). 😄 Most of the increase is somehow system-related, though, not JS-land stuff - it says the total allocated went from ~40MB to ~50MB, but only about 2MB of that difference was directly JS-related, so I don't know (maybe the profiler itself poisoning the report?). 😕 |
@tivac Mind taking another look? |
Full merge ahead! |
I added the "backport to v1" label. We can still keep most of the same code, just if it returns Edit: I should've done that in the first place. |
This was supposed to be purely additive. See here for more details: MithrilJS#1949 (comment)
This was supposed to be purely additive. See here for more details: MithrilJS#1949 (comment)
This was supposed to be purely additive. See here for more details: MithrilJS#1949 (comment)
This was supposed to be purely additive. See here for more details: #1949 (comment)
Optimize events, support objects with `handleEvent`
…JS#2222) This was supposed to be purely additive. See here for more details: MithrilJS#1949 (comment)
Description
Changed/optimized event handling, and added support for objects with
handleEvent
. I also made a few drive-by fixes, as detailed in the last two commits' messages.Each of the two main commits could be taken standalone, and if the second is dropped, I can redo the included fixes in a separate PR (they're all mostly trivial).
In addition, the first commit can be backported with little modification to v1 without breakage (unless people actually rely on being able to wrap Mithril-created event handlers).
Motivation and Context
See #1939 for
handleEvent
. The event subscription changes are to reduce the memory overhead for adding multiple events and changing existing events.As a result, I had to switch to using
addEventListener
andremoveEventListener
exclusively.How Has This Been Tested?
Reused @spacejack's tests for
handleEvent
. (I could've cherry-picked them from his branch, but I was too lazy to.)And yes, I've run the tests locally. 😉
Types of changes