summaryrefslogtreecommitdiff
path: root/src/api/callback.cc
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2020-07-12 03:10:25 +0200
committerAnna Henningsen <anna@addaleax.net>2020-07-14 13:14:27 +0200
commit460c81dc0e088e696e9a7a476254ff381e8474ce (patch)
tree8ba4a198f5e065b1319bf7ae5fcc960f652beac3 /src/api/callback.cc
parentc7627da837af55e3a37ca0933b6a3247fc6c06bb (diff)
downloadnode-new-460c81dc0e088e696e9a7a476254ff381e8474ce.tar.gz
async_hooks: improve resource stack performance
Removes some of the performance overhead that came with `executionAsyncResource()` by using the JS resource array only as a cache for the values provided by C++. The fact that we now use an entry trampoline is used to pass the resource without requiring extra C++/JS boundary crossings, and the direct accesses to the JS resource array from C++ are removed in all fast paths. This particularly improves performance when async hooks are not being used. This is a continuation of https://github.com/nodejs/node/pull/33575 and shares some of its code with it. ./node benchmark/compare.js --new ./node --old ./node-master --runs 30 --filter messageport worker | Rscript benchmark/compare.R [00:06:14|% 100| 1/1 files | 60/60 runs | 2/2 configs]: Done confidence improvement accuracy (*) (**) (***) worker/messageport.js n=1000000 payload='object' ** 12.64 % ±7.30% ±9.72% ±12.65% worker/messageport.js n=1000000 payload='string' * 11.08 % ±9.00% ±11.98% ±15.59% ./node benchmark/compare.js --new ./node --old ./node-master --runs 20 --filter async-resource-vs-destroy async_hooks | Rscript benchmark/compare.R [00:22:35|% 100| 1/1 files | 40/40 runs | 6/6 configs]: Done confidence improvement accuracy (*) async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='async' type='async-local-storage' benchmarker='autocannon' 1.60 % ±7.35% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='async' type='async-resource' benchmarker='autocannon' 6.05 % ±6.57% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='async' type='destroy' benchmarker='autocannon' * 8.27 % ±7.50% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='callbacks' type='async-local-storage' benchmarker='autocannon' 7.42 % ±8.22% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='callbacks' type='async-resource' benchmarker='autocannon' 4.33 % ±7.84% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='callbacks' type='destroy' benchmarker='autocannon' 5.96 % ±7.15% (**) (***) async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='async' type='async-local-storage' benchmarker='autocannon' ±9.84% ±12.94% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='async' type='async-resource' benchmarker='autocannon' ±8.81% ±11.60% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='async' type='destroy' benchmarker='autocannon' ±10.07% ±13.28% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='callbacks' type='async-local-storage' benchmarker='autocannon' ±11.01% ±14.48% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='callbacks' type='async-resource' benchmarker='autocannon' ±10.50% ±13.81% async_hooks/async-resource-vs-destroy.js n=1000000 duration=5 connections=500 path='/' asyncMethod='callbacks' type='destroy' benchmarker='autocannon' ±9.58% ±12.62% Refs: https://github.com/nodejs/node/pull/33575 PR-URL: https://github.com/nodejs/node/pull/34319 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Diffstat (limited to 'src/api/callback.cc')
-rw-r--r--src/api/callback.cc21
1 files changed, 13 insertions, 8 deletions
diff --git a/src/api/callback.cc b/src/api/callback.cc
index 9f52c25cf0..2bb34b088f 100644
--- a/src/api/callback.cc
+++ b/src/api/callback.cc
@@ -160,12 +160,16 @@ MaybeLocal<Value> InternalMakeCallback(Environment* env,
Local<Function> hook_cb = env->async_hooks_callback_trampoline();
int flags = InternalCallbackScope::kNoFlags;
- int hook_count = 0;
+ bool use_async_hooks_trampoline = false;
+ AsyncHooks* async_hooks = env->async_hooks();
if (!hook_cb.IsEmpty()) {
+ // Use the callback trampoline if there are any before or after hooks, or
+ // we can expect some kind of usage of async_hooks.executionAsyncResource().
flags = InternalCallbackScope::kSkipAsyncHooks;
- AsyncHooks* async_hooks = env->async_hooks();
- hook_count = async_hooks->fields()[AsyncHooks::kBefore] +
- async_hooks->fields()[AsyncHooks::kAfter];
+ use_async_hooks_trampoline =
+ async_hooks->fields()[AsyncHooks::kBefore] +
+ async_hooks->fields()[AsyncHooks::kAfter] +
+ async_hooks->fields()[AsyncHooks::kUsesExecutionAsyncResource] > 0;
}
InternalCallbackScope scope(env, resource, asyncContext, flags);
@@ -175,12 +179,13 @@ MaybeLocal<Value> InternalMakeCallback(Environment* env,
MaybeLocal<Value> ret;
- if (hook_count != 0) {
- MaybeStackBuffer<Local<Value>, 16> args(2 + argc);
+ if (use_async_hooks_trampoline) {
+ MaybeStackBuffer<Local<Value>, 16> args(3 + argc);
args[0] = v8::Number::New(env->isolate(), asyncContext.async_id);
- args[1] = callback;
+ args[1] = resource;
+ args[2] = callback;
for (int i = 0; i < argc; i++) {
- args[i + 2] = argv[i];
+ args[i + 3] = argv[i];
}
ret = hook_cb->Call(env->context(), recv, args.length(), &args[0]);
} else {