feat(eventListener): fix #798, improve EventTarget.addEventListener performance#812
feat(eventListener): fix #798, improve EventTarget.addEventListener performance#812mhevery merged 10 commits intoangular:masterfrom
Conversation
|
I added a performance test here: 3a017d3 Right away two things jump out.
The GC problem means that we are still creating too many objects. Can we do an audit and see if every one of these objects is needed? |
|
The issue is coming from try {
// In cross site contexts (such as WebDriver frameworks like Selenium),
// accessing the handler object here will cause an exception to be thrown which
// will fail tests prematurely.
validZoneHandler = data.handler && data.handler.toString() === '[object FunctionWrapper]';
} catch (error) {
// we can still try to add the data.handler even we are in cross site context
data.crossContext = true;
return data.invokeAddFunc(addFnSymbol, data.handler);
}
|
|
@mhevery , thank you for review! I tried several approaches and did some test.
Approach 1. current PR version.
Approach 2. comment the
|
|
@JiaLiPassion WOW, very impressive analysis! Kudos for such amazing work and insight! Yes approach 4/5 seems a way to go. It is our best hope to decrease the memory pressure and increases registration speed. In approach 5 how would task cancelation/rescheduling work? We have to make sure that this would continue to work. const someZone = Zone.current.fork({
name: 'someZone',
onScheduleTask:
(delegate: ZoneDelegate, current: Zone, target: Zone, task: Task):
Task => {
// Blacklist scroll, mouse, and request animation frame events.
if ((task.type === 'eventTask' || task.type === 'macroTask') &&
isBlacklistedEvent(task.source)) {
task.cancelScheduleRequest();
// Schedule task in root zone, note Zone.root != target,
// "target" Zone is Angular. Scheduling a task within Zone.root
// will prevent the infinite digest cycle from appearing.
return Zone.root.scheduleTask(task);
} else {
return delegate.scheduleTask(target, task);
}
}
});``` |
|
@mhevery , got it, I will try to find out Approach 5 work or not. |
Status
now the performance result is
native: 150ms 3.5x slower than native and 3x faster than current version.
native: 170 ms 3x slower than native and 3x faster than current version. changes from current implementation.add different handlers for same event , internal behavior changes
This is the biggest changes from current implementation.
will only run when browser is IE/Edge and cross context check is enabled by set Improvement point.Basically one point only.
Some codes may look ugly such as https://github.com/angular/zone.js/pull/812/files#diff-06332d8779803ae538dab973c558d328R218, the purpose is ** don't create additional objects ** Please review! Thank you! |
…ner performance
b27622f to
5110e35
Compare
|
awesome progress...
…On Wed, Jun 21, 2017 at 7:16 PM, JiaLiPassion ***@***.***> wrote:
Progress.
Use Approach 5. still schedule event task, now the performance data will be
350~450 ms, it will be 3x native version, and I will continue to add some
optimization for zone.scheduleEventTask to remove some not needed
try/catch or new Function
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#812 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAG1T5qS1_KLR6MMMnWftE2rrggxEci5ks5sGU_SgaJpZM4N2cXP>
.
|
|
@mhevery , thank you! currently all the test has passed, please review. And I will continue to check other tasks such as |
mhevery
left a comment
There was a problem hiding this comment.
- Minor changes requested
- It seems like we have added a lot of new code but have not deleted existing code. What is going?
- Could we somehow get this better packaged into
__load_patchso that it is cleaner?
| const zoneSymbolEventNames: any = {}; | ||
| const globalSources: any = {}; | ||
|
|
||
| const _global: any = |
There was a problem hiding this comment.
Could we get this from the patch function global? It would be better if we checked for global in exactly one place.
There was a problem hiding this comment.
yeah, I will move this code into __load_patch
| const BROWSER_TOOLS = 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }'; | ||
|
|
||
| // predefine all __zone_symbol__ + eventName + true/false string | ||
| eventNames.forEach((eventName: string) => { |
There was a problem hiding this comment.
could we use for loop for perf reasons?
There was a problem hiding this comment.
yes, will do.
| }); | ||
|
|
||
| // predefine all task.source string | ||
| WTF_ISSUE_555.split(',').forEach((target: string) => { |
There was a problem hiding this comment.
could we use for loop for perf reasons?
|
also thank you for the awesome work on investigating the perf and getting it down. |
|
@mhevery , I have updated the code.
target.addListener('msg', function() {
// here we can not get the event type which should be `msg`.
});so we can't use But we can still benefit from other improvements, so I will move this PR's new
I will continue to make this code also work for |
|
@mhevery , I have updated the source.
new callback: 700ms
new callback: 440ms
Please review, Thank you. |

fix #798.
EventTarget.addEventListenerperformance with @mhevery 's idea which described in Slow addEventListener performance. #798, we will not save aeventTasklist onevent target, and will not go through thiseventTasklist to find whether we have already registered the event or not.instead we save the information to
callbackitself, sowill not slow down
nodejswe still use the original way to savetaskList,because in the
eventListenercallback, there is noeventNameinformation, andnodejssupport to add the identical listener multiple times.