Skip to content
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

domain: allow concurrent user-land impl #26326

Closed

Conversation

misterdjules
Copy link

Currently, only one domain-like implementation (the core domain one) can be used to handle uncaught exceptions or unhandled error events.

This PR aims at making it possible for different domain-like user-land implementations to be used concurrently (including with the core domain impl) so that the state of the core domain module (doc deprecated) does not prevent users of domains from having a well-maintained domain-like facility.

Ref: #23348

This is the second iteration of #24279, which uses a different approach to allow user-land implementations of a domain-like facility:

  1. it allows to register only one uncaught exception callback (but it still allows the uncaught exception callback to be set by any caller even after the core domain module set it).

  2. it moves the domains stack from being owned by the domain module to being shared by all domain-like implementations

  3. it moves the handling of domains back into lib/events, as otherwise making it so that event emitter instances created within the context of different domain-like implementation have the proper implementation of EventEmitter methods without clobbering other domain modules' implementation of those methods seemed a bit convoluted. I think ideally we would allow each domain implementation to have their own EventEmitter overrides that don't conflict with each other, and if that's the only point of contention for this PR we can definitely address it in subsequent iterations/commits in this PR.

These changes have been tested by implementing a user-land domain-like module and using it as a replacement for domain in restify.

If that approach seems reasonable, there is probably a number of new tests that we can add to the tests suite, but I'd like to get some feedback before adding those.

/cc @nodejs/domains

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-bot
Copy link
Collaborator

@misterdjules sadly an error occured when I tried to trigger a build :(

@nodejs-github-bot nodejs-github-bot added domain Issues and PRs related to the domain subsystem. errors Issues and PRs related to JavaScript errors originated in Node.js core. events Issues and PRs related to the events subsystem / EventEmitter. labels Feb 26, 2019
@@ -32,7 +32,9 @@ module.exports = EventEmitter;
EventEmitter.EventEmitter = EventEmitter;

EventEmitter.usingDomains = false;
EventEmitter.domainSym = Symbol('isDomainLike');
Copy link
Member

@devsnek devsnek Feb 26, 2019

Choose a reason for hiding this comment

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

symbol descriptions should match how they are accessed. Symbol('events.domainSym')

Copy link
Author

Choose a reason for hiding this comment

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

Sounds good, will fix!

Copy link
Member

Choose a reason for hiding this comment

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

I’d prefer EventEmitter.isDomainLike in that case :) Also, should this be documented, since the idea is making it available to other implementations (it is, right)?

Copy link
Author

Choose a reason for hiding this comment

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

I’d prefer EventEmitter.isDomainLike in that case :)

Sounds good, given there might be a lot of different opinions on the naming of this property, let's leave that to the final stages of this review :)

Also, should this be documented, since the idea is making it available to other implementations (it is, right)?

Yes, the idea is to make it available to other implementations. You can take a look at how it's used in the proof-of-concept that I wrote to test this.


// It's possible to enter one domain while already inside another one. The stack
// is each entered domain.
const stack = exports._stack = process._domainsStack;
Copy link
Member

Choose a reason for hiding this comment

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

can you revert the change to this line?

Copy link
Author

Choose a reason for hiding this comment

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

What do you mean? How would stack and exports._stack be initialized?

Copy link
Member

Choose a reason for hiding this comment

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

The general goal is to avoid doing x = y = z

this would work:

const stack = process._domainStack;
exports._stack = stack; // no change to this line

or better yet, remove the const stack = entirely and just refer to process._domainStack.

Copy link
Author

Choose a reason for hiding this comment

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

Sounds good, will do!

Copy link
Member

@vdeturckheim vdeturckheim left a comment

Choose a reason for hiding this comment

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

LGTM!

Currently, only one domain-lke implementation (the core domain one) can
be used to handle uncaught exceptions or unhandled error events.

This PR aims at making it possible for different domain-like
user-land implementations to be used concurrently (including with the
core domain impl) so that the state of the core domain module (doc
deprecated) does not prevent users of domains from having a
well-maintained domain-like facility.

Ref: nodejs#23348
@misterdjules
Copy link
Author

@addaleax I would love to read your thoughts on this as I think you had some objections to the previous approach that I used to allow user-land domain implementations.


The stack trace is extended to include the point in time at which the
`domain` module had been loaded.

Copy link
Member

Choose a reason for hiding this comment

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

We have a special section for error codes that were removed, could you move these there (and add a removed: REPLACEME YAML tag)?

Copy link
Author

Choose a reason for hiding this comment

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

Yes 👍 I keep forgetting about that, my apologies.

@@ -32,7 +32,9 @@ module.exports = EventEmitter;
EventEmitter.EventEmitter = EventEmitter;

EventEmitter.usingDomains = false;
EventEmitter.domainSym = Symbol('isDomainLike');
Copy link
Member

Choose a reason for hiding this comment

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

I’d prefer EventEmitter.isDomainLike in that case :) Also, should this be documented, since the idea is making it available to other implementations (it is, right)?

@addaleax
Copy link
Member

@BridgeAR
Copy link
Member

BridgeAR commented Mar 1, 2019

                                                 confidence improvement accuracy (*)   (**)  (***)
events/ee-emit.js listeners=10 argc=0 n=2000000         ***    -13.80 %       ±1.78% ±2.39% ±3.13%
events/ee-emit.js listeners=10 argc=10 n=2000000        ***    -32.66 %       ±0.92% ±1.24% ±1.62%
events/ee-emit.js listeners=10 argc=2 n=2000000         ***    -23.67 %       ±1.03% ±1.38% ±1.80%
events/ee-emit.js listeners=10 argc=4 n=2000000         ***    -26.41 %       ±0.82% ±1.09% ±1.43%
events/ee-emit.js listeners=1 argc=0 n=2000000          ***    -23.44 %       ±4.26% ±5.72% ±7.56%
events/ee-emit.js listeners=1 argc=10 n=2000000         ***    -29.89 %       ±2.34% ±3.12% ±4.09%
events/ee-emit.js listeners=1 argc=2 n=2000000          ***    -25.91 %       ±2.69% ±3.57% ±4.65%
events/ee-emit.js listeners=1 argc=4 n=2000000          ***    -27.00 %       ±2.31% ±3.08% ±4.01%
events/ee-emit.js listeners=5 argc=0 n=2000000          ***    -18.14 %       ±3.21% ±4.29% ±5.60%
events/ee-emit.js listeners=5 argc=10 n=2000000         ***    -27.51 %       ±1.23% ±1.64% ±2.15%
events/ee-emit.js listeners=5 argc=2 n=2000000          ***    -20.26 %       ±1.34% ±1.79% ±2.34%
events/ee-emit.js listeners=5 argc=4 n=2000000          ***    -21.42 %       ±1.47% ±1.96% ±2.56%

Events seem to take quite a hit due to the changes.

@misterdjules
Copy link
Author

Events seem to take quite a hit due to the changes.

Oh, that seems pretty bad indeed. Let me take a look within the next few days and see whether we can avoid that performance penalty.

@BridgeAR
Copy link
Member

Ping @misterdjules

@misterdjules
Copy link
Author

@BridgeAR Thanks for the ping! This is still on my radar, but I've had other work priorities conflict with this. Not sure when I'll be able to allocate any time to iterate on the current implementation, hopefully sooner than later.

@BridgeAR
Copy link
Member

BridgeAR commented Dec 20, 2019

@misterdjules is this still something you would like to work on?

@misterdjules
Copy link
Author

@BridgeAR Thanks for the ping!

I'd still like something similar (allowing full-featured user land domain implementations to coexist alongside the core domain one) to happen, regardless of whether this is done using the approach in this PR or using a different approach. I also don't mind if someone else finishes what remains to be done.

I don't know if I'll have more time to dedicate to this soon.

Are you asking to determine whether this can be closed? Maybe tagging this with the stalled label would be appropriate here?

@Trott
Copy link
Member

Trott commented Apr 22, 2020

I'm in the process of rebasing this, and want to leave some notes:

@Trott
Copy link
Member

Trott commented Apr 22, 2020

Successfully rebased but can't force push to @misterdjules's branch...

@misterdjules
Copy link
Author

@Trott Are you still blocked by not having force push access to my branch or are you fine with continuing your work at #33013? Regardless, thank you so much for picking this up 🙏

@Trott
Copy link
Member

Trott commented May 4, 2020

@Trott Are you still blocked by not having force push access to my branch or are you fine with continuing your work at #33013? Regardless, thank you so much for picking this up 🙏

I'm fine picking it up in #33013 although even better if someone else does, because I don't know when I'm going to get around to looking at those performance regressions.

I think this one can be closed, unless you plan on picking it back up (in which case I'll close #33013).

@misterdjules
Copy link
Author

@Trott I do not plan to pick this up.

@Trott Trott closed this May 7, 2020
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. errors Issues and PRs related to JavaScript errors originated in Node.js core. events Issues and PRs related to the events subsystem / EventEmitter.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants