-
Notifications
You must be signed in to change notification settings - Fork 7
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
MakeCallback is very slow #24
Comments
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. |
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 :) |
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. |
async_hooks have a tiny overhead if disabled and a significant overhead if enabled. |
Is it possible to disable it? |
Not really. That's described in the linked issue. Maybe a compile-time flag could do it but we are talking ns of difference. |
see also previous related work in |
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 |
@H4ad that would work for people using AsyncLocalStorage but not for people otherwise using 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. |
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 |
Yes, mostly. Though promises are an order of magnitude larger overhead than tick or timer callbacks. The overhead is non-zero though, so in a hot path which calls MakeCallback often it could make a difference to optimize it with that no-op delegate I mentioned. Not sure if/when I'll get time to do something about that but I'd like to try it at some point. 🤔 |
The linked-to "ALIEN_UWS" is a valid benchmark of the imposed perf. loss for native addons in Node.js, vs. those written entirely against V8. You can clearly see how significant the loss is, on a whole web server just trying to deliver events to JS. If you enable(d) ALIEN_UWS (which was removed), vanilla V8 function call was used instead of node::MakeCallback which boosted perf. of the entire web server by 35%. That's not a boost for some simple for-loop doing some addition operation or something like that - that's 35% overall performance boost of an entire HTTP server in full. So the overhead of node::MakeCallback is severe. For about a decade, this has been known and we do lose about 40% of total perf. only due to node::MakeCallback. If we swap to V8 Function call, we lose about 20% of the native perf. What I ultimately decided on, was to introduce a short lived HTTP cache in uWS.js so that fewer calls into JS are needed, and this boosted perf. to the top. So we are very much limited by node::MakeCallback and it is a shame that the vanilla V8 performance is not reflected in Node.js. |
Calling into JS from CPP is very slow. Is this due to async hooks? Could we disable that with a global option if the user doesn't need async hooks?
The text was updated successfully, but these errors were encountered: