You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
See past discussions nodejs/node#10101 - I think the conclusion was that it wasn't that slow, but that was measured 6 years ago and before V8 rolled out several architectural redesigns. We have also deprecated domains for a long time. Maybe the situations have changed now. Would be good to have some new measurements to see if it is worth a shot making it some kind of optional thing.
Interesting stuff (though bad manners) at uNetworking/uWebSockets.js#904 namely that experiment (that does break async_hooks but also improves performance)
I could be wrong, but once this nodejs/node#48528 is merged, we can probably rewrite MakeCallback to use AsyncContextFrame, right? Assuming AsyncContextFrame is faster than async_hooks.
I've been wanting to split all the async_hooks stuff in C++ out into a delegate class which we could use a no-op version for until a hook is registered. That would make it easier to at least contain the overhead when it's not in-use.
Reacted by Matteo Collina, Robert Nagy and Vinicius Lourenço
My understanding (or, from nodejs/node#10101) is that async hooks do not actually contribute much to the overhead when it's not enabled - and it's opt-in already so users would be willingly taking the hit. Most of the overhead comes from the tick callback for process.nextTick. While it also only incurs a lot of overhead when actually used, due to the prevalence of its usage in Node.js internals and the user land, the overhead is also much more prevalent. Doing something about async hooks helps a bit, but it's also only a very small piece of the puzzle because it's actually not used that much in the user land. process.nextTick() is the real beast here that affect almost all use cases.
src: do not shrink async resources on every pop node#66344: the async resources deque is not freed on every pop. On Linux no change, on Windows (MSVC) and macOS (libc++) it saves an alloc and a free per callback (136-147 ns -> 6 ns in a small program). Two approvals, needs only CI and commit-queue.
Activity
joyeecheung commentedon Nov 21, 2022
See past discussions nodejs/node#10101 - I think the conclusion was that it wasn't that slow, but that was measured 6 years ago and before V8 rolled out several architectural redesigns. We have also deprecated domains for a long time. Maybe the situations have changed now. Would be good to have some new measurements to see if it is worth a shot making it some kind of optional thing.
anonrig commentedon Nov 21, 2022
Can you explain this in detail? I'm trying to understand the current implementation, and a quick explanation could/would save a lot of time :)
ronag commentedon Nov 22, 2022
I don't know much about the details. Async hooks are used to propagate async context. It has a constant overhead even if you don't use it.
mcollina commentedon Nov 22, 2022
async_hooks have a tiny overhead if disabled and a significant overhead if enabled.
ronag commentedon Nov 22, 2022
Is it possible to disable it?
mcollina commentedon Nov 22, 2022
Not really. That's described in the linked issue. Maybe a compile-time flag could do it but we are talking ns of difference.
abenhamdine commentedon Dec 1, 2022
see also previous related work in
nodejs/node#41331
nodejs/node#41279
some big picture datapoints here, related to uWebSockets module : uNetworking/uWebSockets.js#341
benjamingr commentedon May 23, 2023
Interesting stuff (though bad manners) at uNetworking/uWebSockets.js#904 namely that experiment (that does break async_hooks but also improves performance)
H4ad commentedon Jul 11, 2023
I could be wrong, but once this nodejs/node#48528 is merged, we can probably rewrite
MakeCallbackto useAsyncContextFrame, right? AssumingAsyncContextFrameis faster thanasync_hooks.benjamingr commentedon Jul 12, 2023
@H4ad that would work for people using AsyncLocalStorage but not for people otherwise using async hooks
Qard commentedon Oct 2, 2023
I've been wanting to split all the async_hooks stuff in C++ out into a delegate class which we could use a no-op version for until a hook is registered. That would make it easier to at least contain the overhead when it's not in-use.
joyeecheung commentedon Oct 19, 2023
My understanding (or, from nodejs/node#10101) is that async hooks do not actually contribute much to the overhead when it's not enabled - and it's opt-in already so users would be willingly taking the hit. Most of the overhead comes from the tick callback for
process.nextTick. While it also only incurs a lot of overhead when actually used, due to the prevalence of its usage in Node.js internals and the user land, the overhead is also much more prevalent. Doing something about async hooks helps a bit, but it's also only a very small piece of the puzzle because it's actually not used that much in the user land.process.nextTick()is the real beast here that affect almost all use cases.34 remaining items
node-api: find the Environment once
src: add MakeCallback() taking an Environment
benchmark: add a node::MakeCallback benchmark
test: check frame restore in CallbackScope
benchmark: add a node::MakeCallback benchmark
test: check frame restore in CallbackScope
nigrosimone commentedon Nov 9, 2026
Update, one month later. Each PR, what it does and the gain measured in it:
Landed
node::MakeCallback202-208 -> 155-159 ns.AsyncResource::MakeCallbackkeeps the ALS store without a scope. AsyncResource +29/+36%.node::MakeCallback. +12/+13%, 136-141 -> 122-125 ns.Open
node::MakeCallback+7.3%, AsyncResource +8.5%. No review yet.napi_make_callbackfinds the Environment once. +15%, 200 -> 174 ns.MakeCallback()overload taking the Environment. +5/+12%, 133 -> 119 ns.node-api: find the Environment once
src: add MakeCallback() taking an Environment
node-api: find the Environment once
src: add MakeCallback() taking an Environment
node-api: find the Environment once
src: add MakeCallback() taking an Environment
node-api: find the Environment once
src: add MakeCallback() taking an Environment