| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
There was a problem hiding this comment.
Have you benchmarked any potential performance change this could bring for use cases of EventEmitter with domain enabled?
Sorry, something went wrong.
There was a problem hiding this comment.
Why did this get removed?
Sorry, something went wrong.
There was a problem hiding this comment.
It has moved here https://github.com/nodejs/node/pull/17403/files/426afc70832c47f18f9afd9f90f35c1e554c8d3a#diff-0b93f5d72b0d34f5b972b661935344c3R415
The only case when this code was reached was when a domain was present, other situation throw.
Sorry, something went wrong.
There was a problem hiding this comment.
Nice!
Sorry, something went wrong.
There was a problem hiding this comment.
I should remove the else here
Sorry, something went wrong.
I would be okay with a slight performance regression for a long-deprecated module like domain anyway. |
Sorry, something went wrong.
|
@TimothyGu I have no data regarding perf impact here. |
Sorry, something went wrong.
There was a problem hiding this comment.
I'm +1 on the cleanup and not too concerned about performance implications.
Sorry, something went wrong.
|
Re: benchmarks. I don't think we have any for event emitters + domains. |
Sorry, something went wrong.
Sorry, something went wrong.
There was a problem hiding this comment.
We should change this comment. It serves no purpose now, other than backward compatibility.
Sorry, something went wrong.
There was a problem hiding this comment.
Updated!
Sorry, something went wrong.
There was a problem hiding this comment.
Excellent. Only one minor nit.
Sorry, something went wrong.
Yet, for a long time (years) domain was the only thing available that could do the things it could do. I don't foresee any significant performance problem that could stem from this PR, but would like to be safe.
No need to even use domains in a benchmark, measuring the difference between EventEmitter usage with versus without require()ing it suffices. |
Sorry, something went wrong.
There was a problem hiding this comment.
Change itself LGTM.
Sorry, something went wrong.
There was a problem hiding this comment.
Nit: typos
// Override EventEmitter methods to make it domain-aware.
Sorry, something went wrong.
There was a problem hiding this comment.
Updated!
Sorry, something went wrong.
There was a problem hiding this comment.
If this is only meant for 9.x & on, then instead of ...args I would recommend using arguments. There's no risk in V8 6.2 and it's faster, since we're just forwarding the full argument list with no slicing.
Sorry, something went wrong.
Sorry, something went wrong.
There was a problem hiding this comment.
Making my requests more explicit. Would like these changes to get made before it lands but if not, will open a PR afterwards.
Sorry, something went wrong.
| }; | ||
|
|
||
| const eventEmit = EventEmitter.prototype.emit; | ||
| EventEmitter.prototype.emit = function emit(...args) { |
There was a problem hiding this comment.
@vdeturckheim Would you mind changing this to emit() and then using arguments everywhere? I realize performance is not that big of a deal but this will actually make a substantial difference.
Sorry, something went wrong.
There was a problem hiding this comment.
@apapirovski are you sure it's faster? (In recent V8)
Sorry, something went wrong.
There was a problem hiding this comment.
Yeah, I'm certain because I checked it very recently. ...args is only faster when arguments requires slicing or manually copying in situations like emit(type, ...args).
Sorry, something went wrong.
There was a problem hiding this comment.
@apapirovski very interesting can you share a benchmark showing that? I'm pretty sure ...args is optimized.
cc @bmeurer
Sorry, something went wrong.
There was a problem hiding this comment.
It has been optimized but in practical usage it still seems to perform worse. I've run into this working on nextTick, events and timers.
> function fn(...args) {
... return Reflect.apply(Math.max, Math, args);
... }
>
> function fn2() {
... return Reflect.apply(Math.max, Math, arguments);
... }
> console.time('test'); for (var i = 0; i < 1e8; i++) { fn(1, 2, 3, 4); } console.timeEnd('test');
test: 279.502ms
> console.time('test'); for (var i = 0; i < 1e8; i++) { fn2(1, 2, 3, 4); } console.timeEnd('test');
test: 284.195msThe basic benchmark shows it being optimized. As soon as I've tried using it in practice where there's more than one layer to the usage, arguments seems to win out.
Sorry, something went wrong.
There was a problem hiding this comment.
btw @benjamingr I decided to finally split test all the possible variations. Here are my findings:
function fn(...args) {
cb(...args);
}
is the fastest for that particular purpose, faster than using arguments (about 3-5% faster). But then there's:
function fn(something, ...args) {
cb(...args);
}
seems to depend on specific usage of args within fn. For example, I've found that in setTimeout and setImmediate we incur about 20-25% performance penalty compared to using manual copying of arguments.
On the flipside, it performs as expected within EventEmitter.prototype.emit... and is, in fact, yet again faster than using arguments. There definitely seem to be some edge cases around this behaviour that I don't quite understand.
I don't know if this helps with your plan to bug V8 devs regarding this :)
Sorry, something went wrong.
There was a problem hiding this comment.
It's possible this might be related to whether args is being stored somewhere or just passed through to another function, or whether args is accessed at all in the body?
Sorry, something went wrong.
| EventEmitter.prototype.emit = function emit(...args) { | ||
| const domain = this.domain; | ||
| if (domain === null || domain === undefined || this === process) { | ||
| return eventEmit.apply(this, args); |
There was a problem hiding this comment.
Could you use Reflect.apply here (and everywhere else) to avoid any potentially overridden apply methods?
Sorry, something went wrong.
There was a problem hiding this comment.
Why would we use Reflect.apply here but not in the regular event emitter code?
Sorry, something went wrong.
There was a problem hiding this comment.
There's a PR introducing it there too, it's just currently blocked on some other stuff.
Sorry, something went wrong.
There was a problem hiding this comment.
@apapirovski sounds good - although a little defensive (if someone overrides Function.prototype.apply or apply on a function object - they other didn't mean to or they know exactly what they're doing - in both cases I'm not sure Node.js should guard against it.
Sorry, something went wrong.
There was a problem hiding this comment.
We definitely should. The usage of .apply is an implementation detail and should not be affected by monkey-patching.
Sorry, something went wrong.
There was a problem hiding this comment.
Doesn't Reflect.apply have the same "issue"? It is writable too.
Sorry, something went wrong.
There was a problem hiding this comment.
Of course. But it's a step better because we're no longer relying on a method of a user provided function. At least Reflect.apply allows us consistent behaviour between all the different functions that are going to be called, instead of relying on the potentially unique apply of each specific callback.
Strictly speaking, using some sort of an internal way of invoking functions brings us closer to the spec too (e.g. for timers).
Sorry, something went wrong.
There was a problem hiding this comment.
Also, to elaborate, this has become less of an issue lately but it was potentially even more problematic in the past where certain functions were called as callback(arguments[0]) and others callback.apply(undefined, arguments).
Sorry, something went wrong.
|
@apapirovski since @addaleax placed the "ready" flag, I'm not certain I should still do changes :/ |
Sorry, something went wrong.
|
@vdeturckheim Up to you. ready just means it can land but if you want to make changes, you always can. Otherwise I'll just open a PR after this lands. |
Sorry, something went wrong.
|
@apapirovski let's do that in two different PR then, I don't have access to my laptop atm. |
Sorry, something went wrong.
|
Landing now. (Just running local tests one more time to make sure we're all good.) |
Sorry, something went wrong.
PR-URL: #17403 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
|
@addaleax or @AndreasMadsen do we land these changes to domain on 6.x or 8.x? Not sure what the situation is given the deprecation. Want to make sure we get the right labels on this, if necessary. Thanks! |
Sorry, something went wrong.
|
@addaleax I think this is a bug in Node.js actually. We emit error events with non-Error instances. There is also a domain active. Despite having an event handler, the emitted error is considered unhandled. I reckon it's this line in this PR that's causing problems. See https://gist.github.com/novemberborn/2d6137cab8a57fdbafbccc5b33926585. I've tested with node-v10.0.0-nightly20171209e9d1e1265a-darwin-x64.
Neither am I, so either that comes from node-tap or there's a dependency that enters a domain. |
Sorry, something went wrong.
Fix an issue where error is never emitted on the original EventEmitter in situations where a listener for error does exist. Refactor to eliminate unnecessary try/catch/finally block. PR-URL: #17588 Refs: #17403 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#17403 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Fix an issue where error is never emitted on the original EventEmitter in situations where a listener for error does exist. Refactor to eliminate unnecessary try/catch/finally block. PR-URL: nodejs#17588 Refs: nodejs#17403 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
|
the commit neccessary to land after this 04ae486 does not land cleanly. Would someone be willing to manually backport? edit: cf4448c does not land cleanly either |
Sorry, something went wrong.
Fix an issue where error is never emitted on the original EventEmitter in situations where a listener for error does exist. Refactor to eliminate unnecessary try/catch/finally block. Backport-PR-URL: #18487 PR-URL: #17588 Refs: #17403 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
|
@watson managed to track down this commit as breaking, potentially we should have considered it Semver-Major Here is the reproducible case they provided https://gist.github.com/watson/d67b60629026fdb7d081be7477c040e5 The below code will pass on 9.5.0 and fail on 9.6.0 var assert = require('assert')
var EventsModule = require('events')
var descriptor = Object.getOwnPropertyDescriptor(EventsModule, 'usingDomains')
assert(descriptor)I'm going to open a revert against the 9.x branch and potentially release another version later today. Thoughts? |
Sorry, something went wrong.
|
@MylesBorins LGTM. Should it wait until v10 or should we try to do that in a non breaking change way in v9? |
Sorry, something went wrong.
|
Thanks for the quick action @MylesBorins 😃 The test-case was written before I knew what was causing the problem. It's code lifted from bluebird@2.9.24 but could be simplified to just require('assert')(require('events').usingDomains) 😜 |
Sorry, something went wrong.
The line setting this was removed in a previous commit. This potentially breaks code in the wild using this property. Refs: nodejs#17403 (comment)
The line setting this was removed in a previous commit. This potentially breaks code in the wild using this property. Refs: #17403 (comment) PR-URL: #18944 Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
The line setting this was removed in a previous commit. This potentially breaks code in the wild using this property. Refs: #17403 (comment) PR-URL: #18944 Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
The line setting this was removed in a previous commit. This potentially breaks code in the wild using this property. Refs: nodejs#17403 (comment) PR-URL: nodejs#18944 Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
| Back | FazBrowse Home | New Git URL |
Checklist
Affected core subsystem(s)
Events and Domain I removed the domain handling in events to have domain doing that.
Relates to #17143