-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
async_hooks: minor refactor to callback invocation #13419
async_hooks: minor refactor to callback invocation #13419
Conversation
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.
Very nice
lib/async_hooks.js
Outdated
if (typeof active_hooks_array[i][before_symbol] === 'function') { | ||
runCallback(active_hooks_array[i][before_symbol], asyncId); | ||
try { | ||
for (var i = 0; i < active_hooks_array.length; i++) { |
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.
Why not for ... of
?
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 don’t know, but I wouldn’t be surprised if this variant would continue to be faster (i.e. I’m reluctant to change this without benchmarking – if you do and you get good results, sure).
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.
ack
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 original reason for this was that the array index was used. This was before the design decision to not allow the callable hooks to be altered during execution of all hooks; not for benchmarking reasons. Though I'd say no sense in changing it unless benchmarks show there is an improvement.
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.
Ack.
Was curious so I just tested and FOI (For Our Information):
> var a = [1]
undefined
> for (let b of a) { b === 1 && a.push(2); console.log(b)}
1
2
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.
@refack That's no longer an issue, which is why the index is no longer used. At the top of the file you'll see:
// Use to temporarily store and updated active_hooks_array if the user enables
// or disables a hook while hooks are being processed.
var tmp_active_hooks_array = null;
// Keep track of the field counts held in tmp_active_hooks_array.
var tmp_async_hook_fields = null;
Which getHooksArray()
automatically assigns the old array to and duplicates the new altered array. So it's impossible for the user to alter the hooks mid-execution. i.e. you'll never see the case of "a.push()
" to the actual array that contains the hooks in the middle of execution. So feel free to benchmark it all you want.
emitBeforeN(asyncId); | ||
} | ||
|
||
|
||
// Called from native. The asyncId stack handling is taken care of there before | ||
// this is called. | ||
function emitAfterN(asyncId) { | ||
if (async_hook_fields[kAfter] > 0) { | ||
processing_hook = true; | ||
processing_hook = true; |
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.
Why was the if (async_hook_fields[kAfter] > 0)
short circuit removed?
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’ve added it to emitAfterS
now; The idea is that the native code doesn’t bother calling emitAfterN
if the field is 0, so checking it here is pointless for the common case of a call from 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.
Note for future change: I'd like to include a macros.py
similar to deps/v8/src/js/macros.py
for Debug builds. except it replaces comments instead of normal expressions.
In the code you'll find // CHECK()
comments that were meant as reminders of important bits to check, but not important enough to check in a Release build. Though the difference would be that
// CHECK(expr)
is replaced with something like
assert.ok(expr);
But only for debug builds.
Point here would be to include the following here:
// CHECK(async_hook_fields[kAfter] > 0)
as a sanity check for the future in case a change is made that invalidates your comment of
The idea is that the native code doesn’t bother calling
emitAfterN
if the field is 0, so checking it here is pointless for the common case of a call from C++.
lib/async_hooks.js
Outdated
@@ -412,11 +397,17 @@ function emitDestroyS(asyncId) { | |||
|
|||
|
|||
function emitDestroyN(asyncId) { | |||
if (async_hook_fields[kDestroy] === 0) return; |
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.
Re: https://github.com/nodejs/node/pull/13419/files#r119971593 why was this added?
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.
Right, this is superfluous, thanks for pointing out.
b347faa
to
91a6e96
Compare
@refack @AndreasMadsen Thanks for pointing these out, this is updated now |
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
@addaleax Mind adding a comment either in the code or commit message body about why moving the try/catch outside the for loop is an improvement? I have no issue w/ it. Just for posterity. |
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.
Left a comment about leaving a more detailed comment, but not a blocker. LGTM
Re-use the `init` function wherever possible, and move `try { … } catch` blocks that result in fatal errors to a larger scope. Also make the argument order for `init()` consistent in the codebase.
91a6e96
to
868abac
Compare
Rebased and added a comment about the |
Landed in 02aea06 |
Re-use the `init` function wherever possible, and move `try { … } catch` blocks that result in fatal errors to a larger scope. Also make the argument order for `init()` consistent in the codebase. PR-URL: nodejs#13419 Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Re-use the `init` function wherever possible, and move `try { … } catch` blocks that result in fatal errors to a larger scope. Also make the argument order for `init()` consistent in the codebase. PR-URL: #13419 Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Re-use the
init
function wherever possible, and movetry { … } catch
blocks that result in fatal errors to a largerscope.
Also make the argument order for
init()
consistent in the codebase.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
async_hooks /cc @nodejs/async_hooks