FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

events: remove domain handling from events to domain by vdeturckheim · Pull Request #17403 · nodejs/node · GitHub

/ node Public

events: remove domain handling from events to domain - #17403

Closed
vdeturckheim wants to merge 1 commit into
nodejs:masterfrom
vdeturckheim:remove_domains_from_events
Closed

events: remove domain handling from events to domain#17403
vdeturckheim wants to merge 1 commit into
nodejs:masterfrom
vdeturckheim:remove_domains_from_events

Conversation

Copy link
Copy Markdown
Member
Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included (N/A)
  • documentation is changed or added (N/A)
  • commit message follows commit guidelines
Affected core subsystem(s)

Events and Domain I removed the domain handling in events to have domain doing that.
Relates to #17143

nodejs-github-bot added domain Issues and PRs related to the domain subsystem. events Issues and PRs related to the events subsystem / EventEmitter. labels Nov 30, 2017

TimothyGu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Have you benchmarked any potential performance change this could bring for use cases of EventEmitter with domain enabled?

Comment thread lib/events.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why did this get removed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

addaleax left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Nice!

Comment thread lib/events.js Outdated

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I should remove the else here

Copy link
Copy Markdown
Member

Have you benchmarked any potential performance change this could bring for use cases of EventEmitter with domain enabled?

I would be okay with a slight performance regression for a long-deprecated module like domain anyway.

Copy link
Copy Markdown
Member Author

@TimothyGu I have no data regarding perf impact here.

benjamingr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm +1 on the cleanup and not too concerned about performance implications.

Copy link
Copy Markdown
Member

Re: benchmarks. I don't think we have any for event emitters + domains.

Copy link
Copy Markdown
Member

Comment thread lib/domain.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

We should change this comment. It serves no purpose now, other than backward compatibility.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Updated!

AndreasMadsen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Excellent. Only one minor nit.

Copy link
Copy Markdown
Member

@addaleax

I would be okay with a slight performance regression for a long-deprecated module like domain anyway.

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.

@benjamingr

Re: benchmarks. I don't think we have any for event emitters + domains.

No need to even use domains in a benchmark, measuring the difference between EventEmitter usage with versus without require()ing it suffices.

TimothyGu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Change itself LGTM.

Comment thread lib/domain.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Nit: typos

// Override EventEmitter methods to make it domain-aware.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Updated!

apapirovski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

addaleax commented Dec 1, 2017

Copy link
Copy Markdown
Member

addaleax added the author ready PRs that have at least one approval, no outstanding review comments, and a CI started. label Dec 1, 2017

apapirovski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Making my requests more explicit. Would like these changes to get made before it lands but if not, will open a PR afterwards.

Comment thread lib/domain.js
};

const eventEmit = EventEmitter.prototype.emit;
EventEmitter.prototype.emit = function emit(...args) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@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.

benjamingr Dec 4, 2017
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@apapirovski are you sure it's faster? (In recent V8)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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).

benjamingr Dec 4, 2017
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@apapirovski very interesting can you share a benchmark showing that? I'm pretty sure ...args is optimized.

cc @bmeurer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.195ms

The 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.

apapirovski Dec 6, 2017
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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 :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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?

Comment thread lib/domain.js
EventEmitter.prototype.emit = function emit(...args) {
const domain = this.domain;
if (domain === null || domain === undefined || this === process) {
return eventEmit.apply(this, args);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Could you use Reflect.apply here (and everywhere else) to avoid any potentially overridden apply methods?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why would we use Reflect.apply here but not in the regular event emitter code?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

There's a PR introducing it there too, it's just currently blocked on some other stuff.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

We definitely should. The usage of .apply is an implementation detail and should not be affected by monkey-patching.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Doesn't Reflect.apply have the same "issue"? It is writable too.

apapirovski Dec 4, 2017
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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).

apapirovski Dec 4, 2017
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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).

Copy link
Copy Markdown
Member Author

@apapirovski since @addaleax placed the "ready" flag, I'm not certain I should still do changes :/

Copy link
Copy Markdown
Contributor

@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.

Copy link
Copy Markdown
Member Author

@apapirovski let's do that in two different PR then, I don't have access to my laptop atm.

apapirovski commented Dec 4, 2017
edited
Loading

Copy link
Copy Markdown
Contributor

Landing now. (Just running local tests one more time to make sure we're all good.)

Copy link
Copy Markdown
Contributor

Landed in cf4448c

Thanks!!

apapirovski closed this Dec 4, 2017
apapirovski pushed a commit that referenced this pull request Dec 4, 2017
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>

Copy link
Copy Markdown
Contributor

@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!

Copy link
Copy Markdown

@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.

I would not be aware that they use the domain module

Neither am I, so either that comes from node-tap or there's a dependency that enters a domain.

apapirovski added a commit that referenced this pull request Dec 13, 2017
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>
apapirovski pushed a commit to apapirovski/node that referenced this pull request Jan 31, 2018
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>
apapirovski added a commit to apapirovski/node that referenced this pull request Jan 31, 2018
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>

MylesBorins commented Feb 20, 2018
edited
Loading

Copy link
Copy Markdown
Contributor

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

MylesBorins pushed a commit that referenced this pull request Feb 20, 2018
Backport-PR-URL: #18487
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>
MylesBorins pushed a commit that referenced this pull request Feb 20, 2018
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>
MylesBorins mentioned this pull request Feb 21, 2018

Copy link
Copy Markdown
Contributor

@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?

Copy link
Copy Markdown
Member Author

@MylesBorins LGTM. Should it wait until v10 or should we try to do that in a non breaking change way in v9?

watson commented Feb 22, 2018

Copy link
Copy Markdown
Member

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) 😜

MylesBorins added a commit to MylesBorins/node that referenced this pull request Feb 22, 2018
The line setting this was removed in a previous commit. This
potentially breaks code in the wild using this property.

Refs: nodejs#17403 (comment)
gibfahn added the semver-major PRs that contain breaking changes and should be released in the next major version. label Feb 22, 2018
MylesBorins added a commit that referenced this pull request Feb 23, 2018
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>
MylesBorins added a commit that referenced this pull request Feb 23, 2018
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>
MayaLekova pushed a commit to MayaLekova/node that referenced this pull request May 8, 2018
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain Issues and PRs related to the domain subsystem. events Issues and PRs related to the events subsystem / EventEmitter. semver-major PRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.


Back | FazBrowse Home | New Git URL