diff options
| author | Anna Henningsen <anna@addaleax.net> | 2020-07-12 03:10:25 +0200 |
|---|---|---|
| committer | Anna Henningsen <anna@addaleax.net> | 2020-07-14 13:14:27 +0200 |
| commit | 460c81dc0e088e696e9a7a476254ff381e8474ce (patch) | |
| tree | 8ba4a198f5e065b1319bf7ae5fcc960f652beac3 /src/api/callback.cc | |
| parent | c7627da837af55e3a37ca0933b6a3247fc6c06bb (diff) | |
| download | node-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.cc | 21 |
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 { |
