-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
lib,src: replace all C++ promises with JS promises #20830
Conversation
Can you link where as a "Refs" in the commit message? |
@TimothyGu we discussed this in person (even though we have meeting notes) two weeks ago. |
Isn't this a desirable property? |
@TimothyGu not really. Monkey patching is for example still important for APMs and there are probably a couple use cases where people rely on being able to monkey patch promises. Not being able to monkey patch those goes AFAIK against the spec. |
Async Hooks are also important to APMs, and monkey patching
There is no spec for |
a happy medium that can let changing these to be monkey-patchable in a separate pr could be using |
@devsnek We don't want to expose any |
First - do we have benchmarks for this? Second - monkey patching won’t work because of async functions anyway - the future for diagnostics is better hooks Otherwise LGTM |
} else { | ||
promiseResolve(promise, { stdout, stderr }); | ||
} | ||
return new Promise((resolve, reject) => { |
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.
It was written that way to avoid allocation of a closure and be speed-competitive with bluebird.
I’d like to make sure that the speed remains as fast
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.
Yes, we should measure the performance here.
I was suggesting to start with JS promises instead, since we spend some time recently to even inline the promise constructor into TurboFan optimized code. If that turns out to be too slow, then the other alternative is to use the createPromise and friends from v8-extras
, which is also known to TurboFan, and significantly faster than going through C++.
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.
+1 for createPromise from v8-extras.
lib/internal/util.js
Outdated
promiseReject(promise, err); | ||
} | ||
return promise; | ||
return new Promise((resolve, reject) => { |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
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.
LGTM if performance is okay.
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'm only blocking to make sure no one merges this by accident before benchmarks.
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.
This will be somewhere around 10-30% slower than the current version. I tested this fairly recently in relation to promisify. I'll leave it up to others to decide whether that's acceptable.
I chose to discard my own PR due to how much slower it was but perhaps others have a different opinion.
A 30% slower That is, if this PR is significantly slower then I'm very -1 on it. However if the V8 team can make an in-javascript promisify as fast as the current version then I'm +1 on it - and in any case a v8-extras solution should be considered. |
@BridgeAR ... would prefer the changes to different modules to at least be in separate commits. |
@jasnell if this will land at all I would like to keep it in a single commit. I do not see a compelling reason for it to be split into smaller chunks. @apapirovski do you still have the benchmark code you used? Any performance impact is heavily influenced by the task at hand. So benchmarking a promisified setTimeout should show the biggest impact if it has influence on the performance. A general thing: I feel we block to many things for reasons that will have little to no effect on real world applications. |
The compelling reason is to isolate distinct changes in case they need to be reverted or backported separately for any reason. It also makes the changes easier to review module by module. |
@jasnell I think this is fine to land as a single commit – it’s not particularly huge or so, and I don’t think we want to backport any of this anyway because of the perf impact (adding dont-land-on labels). |
@@ -2731,11 +2730,9 @@ function connect(authority, options, listener) { | |||
// Support util.promisify | |||
Object.defineProperty(connect, promisify.custom, { | |||
value: (authority, options) => { | |||
const promise = createPromise(); | |||
const server = connect(authority, |
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.
Actually, it seems we might be able to remove the custom promisifier entirely: what the getter is doing right now should be the exact things done by util.promisify
.
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.
A test fails if that part is removed.
C++ promises can not be properly optimized by V8. They also behave a tiny bit different than "regular" promises.
5627934
to
fb1d667
Compare
@BridgeAR Can you file a follow-up issue on #20830 (comment) when this PR gets landed? |
Landed in bd1f355 🎉 |
C++ promises can not be properly optimized by V8. They also behave a tiny bit different than "regular" promises. PR-URL: nodejs#20830 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
This is just a small refactoring. Refs: nodejs#20830 (comment)
@TimothyGu I personally can not see how that custom promisify should be removed. It is a wrapper for an event and the first argument is always going to be the server. Therefore the http2 case relies on the return value of the function and not on the callback value as that would be registered as an error. If there is something else you had in mind, please let me know! |
Should this be backported to |
C++ promises can not be properly optimized by V8. They also behave a tiny bit different than "regular" promises. PR-URL: nodejs#20830 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
C++ promises can not be properly optimized by V8. They also behave a tiny bit different than "regular" promises. PR-URL: #20830 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Backport-PR-URL: #21879 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
C++ promises can not be properly optimized by V8. They also behave
a tiny bit different than "regular" promises (they can not be monkey patched).
This was requested by @nodejs/v8.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes