-
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
process: improve nextTick performance #25461
Conversation
@mscdex sadly an error occured when I tried to trigger a build :( |
@@ -1,7 +1,7 @@ | |||
'use strict'; | |||
const common = require('../common.js'); | |||
const bench = common.createBenchmark(main, { | |||
n: [5e6] | |||
n: [4e6] |
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.
These were changed to match those found in the other breadth benchmarks and it also seems to provide more stable results.
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.
The fact that we’re emitting one object on init and then pushing another on the next tick queue goes against basic expectations of using async hooks and what the resource is supposed to represent.
Since there are some that believe this should be semver-major, ping @nodejs/tsc |
ping? |
In the context of exposing the current async resource rather than just exposing the asyncId, this change might require to be reverted/changed later. However that work is not settled yet, so we might want to land this anyway, as this code is not really ready for it yet. As an example, we are pursuing this change: #25094 for that reason. cc @nodejs/diagnostics |
ping @nodejs/tsc once more |
There probably won't be a meeting this week, but I'm going to throw a |
(Obviously, if resolution is achieved before the next TSC meeting, that's awesome and I'll be delighted to remove the label at that time.) |
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.
Thanks for working on nextTick
! I've got some questions.
I'm failing to understand why this changes improves performance, and if it may something related to our benchmarks.
Have you tried if moving just the emitInit
call outside of the constructor generates the same result?
Have you verified that is using the same object for both emitInit
and queue.push()
is what is actually creating the performance improvements?
@mscdex have you experiences this improves things in a more realistic scenario including I/O?
Also cc @bmeurer who might provide some insights.
@mcollina I honestly don't remember now, I tried a lot of variations though at the time, and this was the only one that resulted in a positive improvement with no regressions. |
The change looks reasonable to me (JavaScript wise), but I'm really not a good candidate to review this, since this is not my area of expertise. |
@bmeurer have you got a clue on why this is faster than the current one? |
@mcollina Nope, sorry. |
As far as I can tell, this should be mostly related to using symbols which are in my experience slower for both getting and setting properties (and for your version the fact that we use an |
Ping @mscdex |
955cdc1
to
9287f10
Compare
I've made different changes now to avoid the issues with
|
/cc @nodejs/collaborators |
@mscdex does it still fail the test in #25461 (comment)? Maybe we should add it to our suite. |
@mcollina It should not fail it because the same object is being used now. These changes are now more or less inlining the previous custom |
Would you mind adding that test to this PR? Code LGTM. |
@mcollina Honestly I think that's probably best left to a separate issue/PR about whether we should (explicitly) support modifying behavior like that from an async hook callback. |
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
lib/internal/process/task_queues.js
Outdated
callback(...tock.args); | ||
} else { | ||
const args = tock.args; | ||
switch (args.length) { |
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.
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.
Not sure - how much of the improvement is accounted for by this alone (and not the other part of this CL)?
Glancing at e.g. next-tick-depth-args, it doesn't look like the arguments to the callbacks are ever used - maybe we optimize something there. We don't do analysis like that for spread calls
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.
@psmarshall the reason I was concerned is that we removed this optimization from certain parts of the code before.
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 think it's possible to construct a microbenchmark where one or the other is faster - I don't think you could measure the difference on a larger application that does a lot of work between ticks. With that in mind my preference is for the spread-call version but I also don't really have the time to do a detailed analysis of what's going on in this specific case so I'm fine either way.
db72db3
to
34961c7
Compare
Making `.incRef()` and `.decRef()` fail silently leads to better error messages when trying to access the underlying value (as opposed to crashing inside these methods). Refs: #25461 (comment) PR-URL: #29289 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Gus Caplan <[email protected]>
PR-URL: #25461 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
Making `.incRef()` and `.decRef()` fail silently leads to better error messages when trying to access the underlying value (as opposed to crashing inside these methods). Refs: #25461 (comment) PR-URL: #29289 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Gus Caplan <[email protected]>
PR-URL: #25461 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
Making `.incRef()` and `.decRef()` fail silently leads to better error messages when trying to access the underlying value (as opposed to crashing inside these methods). Refs: #25461 (comment) PR-URL: #29289 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Gus Caplan <[email protected]>
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes