-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
napi: improve runtime performance of every napi fun call. #21072
Conversation
Adding a chart, visualizing the data measured by "Blue" vs. "Yellow" is "before PR" vs. "after PR". |
src/node_api.cc
Outdated
napi_env env; // Necessary to invoke C++ NAPI callback | ||
void* cb_data; // The user provided callback data | ||
napi_callback cb[kCallbackCount]; // Max capacity is 2 (getter + setter) | ||
v8::Persistent<v8::Object> handle; // Die with this JavaScript object |
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.
If you use a node::Persistent
you can avoid having to handle.ClearWeak()
and handle.Reset()
in the destructor.
src/node_api.cc
Outdated
// Use WeakCallback mechanism to delete the C++ `bundle` object. | ||
// This will be called when object in `handle` is being GC-ed. | ||
if (CallbackBundle* bundle = info.GetParameter()) { | ||
bundle->handle.Reset(); |
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.
You don't need to Reset()
here.
Maybe you shouldn't compare to pure JS, but rather to a second addon written against the V8 module interface. |
Also, the binding you wrote can (and perhaps should) be compiled using a C compiler. This will happen if you rename the file binding.c. |
@kenny-y this is awesome, BTW, because it gives us a tool for clearly tracking performance, and for objectively tinkering with the implementation. |
src/node_api.cc
Outdated
v8impl::kDataIndex, | ||
v8::External::New(isolate, data)); | ||
v8impl::kCallbackBundleIndex, | ||
v8::External::New(isolate, reinterpret_cast<void*>(bundle))); |
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.
We can actually improve performance even more if
cbdata = v8::External::New(isolate, reinterpret_cast<void*>(bundle))
and then we return the v8::External
directly.
No more need for SetInternalField()/GetInternalField()
, and we don't need the object templates either.
This could be a further improvement, though that doesn't necessarily need to be done in this PR.
@kenny-yuan we cannot really have the NAN version because that would require adding NAN to the Node.js source tree. |
@kenny-yuan I actually tried |
Looping in @nodejs/addon-api. |
I actually built upon @kenny-y's changes to use the ... where "External" builds upon "bundle". So, once we have both changes, a call into a N-API addon will be approximately 75% as performant as a call into a V8 addon, whereas without any of these changes it's only 39% as performant. |
If we want to compare the overhead of calling into JS from N-API and V8, can you add the N-API part into |
There can be only one addon inside on dir. If we want to do both in one dir, we should create 2 subdirs, which is essentially the same... so it's just philosophy of organizing... |
Hi @gabrielschulhof That's good idea to use v8::External as cbdata, there is no other usage of that object, we can definitely use the v8::External to replace it. The below are my data (Code), which show similar trend by using V8::External on top of Bundle, but the v8 bindings data are different to yours -- maybe it's because of the hardware? (esp. freq/icache/dcache?). I'm using an i7-4770K (3.50GHz) desktop, and I can try on others if it's necessary. And also a quick question: do you want to consolidate the bundle + external as one PR? (since this one is still pending) |
@kenny-y I don't think it's necessary to write the two variants in two addons? We can just include |
Also, if different variants are implemented in the same benchmark you can use the benchmark CI to compare them and get a statistical analysis of the results. |
@kenny-y yes, please consolidate the commits into this PR, because removing the function and accessor object templates has memory consumption benefits as well. The definition of the |
@kenny-y in your previous chart you called "V8 Binding" what is essentially a pure JS function call. I would say we should call that "Pure JS", and we should call "V8 Binding" a function call into an addon written directly against V8. That is, we should label the following as "Pure JS": let x = 0;
function pure_js_implementation() {
x++;
} whereas we should label the following as "V8 Binding": const binding = require('./build/Release/binding_v8');
const v8_implementation = binding.hello; where #include <node.h>
static int x = 0;
static void Hello(const v8::FunctionCallbackInfo<v8::Value> info) {
info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), (double)(x++)));
} We should compare the overhead of calling into a N-API callback against the overhead of calling into a V8 callback. |
@kenny-y I was able to add the N-API function call benchmark to the existing misc/function_call benchmark: diff --git a/benchmark/misc/function_call/binding.gyp b/benchmark/misc/function_call/binding.gyp
index 3bfb84493f..af565bd75f 100644
--- a/benchmark/misc/function_call/binding.gyp
+++ b/benchmark/misc/function_call/binding.gyp
@@ -3,6 +3,10 @@
{
'target_name': 'binding',
'sources': [ 'binding.cc' ]
+ },
+ {
+ 'target_name': 'binding_napi',
+ 'sources': [ 'binding_napi.c' ]
}
]
}
diff --git a/benchmark/misc/function_call/binding_napi.c b/benchmark/misc/function_call/binding_napi.c
new file mode 100644
index 0000000000..198cdce2ec
--- /dev/null
+++ b/benchmark/misc/function_call/binding_napi.c
@@ -0,0 +1,21 @@
+#include <assert.h>
+#include <node_api.h>
+
+static uint32_t increment = 0;
+
+static napi_value Hello(napi_env env, napi_callback_info info) {
+ napi_value result;
+ napi_status status = napi_create_uint32(env, increment++, &result);
+ assert(status == napi_ok);
+ return result;
+}
+
+NAPI_MODULE_INIT() {
+ napi_value hello;
+ napi_status status =
+ napi_create_function(env, "hello", NAPI_AUTO_LENGTH, Hello, NULL, &hello);
+ assert(status == napi_ok);
+ status = napi_set_named_property(env, exports, "hello", hello);
+ assert(status == napi_ok);
+ return exports;
+}
diff --git a/benchmark/misc/function_call/index.js b/benchmark/misc/function_call/index.js
index cafff3edc1..257232e88e 100644
--- a/benchmark/misc/function_call/index.js
+++ b/benchmark/misc/function_call/index.js
@@ -19,6 +19,14 @@ try {
}
const cxx = binding.hello;
+try {
+ var binding_napi = require('./build/Release/binding_napi');
+} catch (er) {
+ console.error('misc/function_call.js N-API binding failed to load');
+ process.exit(0);
+}
+const napi = binding_napi.hello;
+
var c = 0;
function js() {
return c++;
@@ -27,12 +35,12 @@ function js() {
assert(js() === cxx());
const bench = common.createBenchmark(main, {
- type: ['js', 'cxx'],
+ type: ['js', 'cxx', 'napi'],
n: [1e6, 1e7, 5e7]
});
function main({ n, type }) {
- const fn = type === 'cxx' ? cxx : js;
+ const fn = type === 'cxx' ? cxx : type === 'napi' ? napi : js;
bench.start();
for (var i = 0; i < n; i++) {
fn(); |
@kenny-y the output was
|
Just a quick reply to the V8 Binding part before hitting the hay: I didn't put JavaScript function call in the chart, "V8 Binding" means a function written in C++ inside an addon and exposed as a JavaScript function in V8 syntax. I'm not sure I'm following, so I just make it more clear by clarifying... :) (and sorry for my English if it's confusing) And maybe we can add JavaScript version as well? (In case people might get curious) P.S. In my environment pure V8 binding outperforms pure JavaScript in a large loop (which is a little bit of weird) Update: today I checked the output again and found pure JS function is always faster than bindings; the wrong impression could be from a bug in my data grabbing script (which is already abandoned)... |
@kenny-y looking back at the data for my previous chart, the pure JS performance dwarfs all others when charted side-by-side – at least on my computer: So, I excluded it because I believe it obscures our performance gains against V8 – which is our target. Yet, if this benchmark is to live alongside V8 and pure JS in |
Multiple targets in one And many thanks to @gabrielschulhof and @joyeecheung for all the info & help. I'll update the source code of this PR. |
d1592f9
to
ebe2377
Compare
src/node_api.cc
Outdated
static const int kFunctionIndex = 2; | ||
static const int kFunctionFieldCount = 3; | ||
// Use this data structure to reduce the number | ||
// of GetInternalField() calls to only 1 (was: 3). |
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.
nit: We no longer access this data via GetInternalField()
. How about we change this comment to
// Use this data structure to associate callback data with each N-API function
// exposed to JavaScript. The structure is stored in a v8::External which gets
// passed into our callback wrapper. This reduces the performance impact of
// calling through N-API.
// Ref: benchmark/misc/function_call
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.
Yep, I did forget to update the comments, my bad.
Added a new struct CallbackBundle to eliminate all GetInternalField() calls. The principle is to store all required data inside a C++ struct, and then store the pointer in the JavaScript object. Before this change, the required data are stored in the JavaScript object in 3 or 4 seperate pointers. For every napi fun call, 3 of them have to be fetched out, which are 3 GetInternalField() calls; after this change, the C++ struct will be directly fetched out by using v8::External::Value(), which is faster. Profiling data show that GetInternalField() is slow. On an i7-4770K (3.50GHz) box, a C++ V8-binding fun call is 8 ns, before this change, napi fun call is 36 ns; after this change, napi fun call is 20 ns. The above data are measured using a modified benchmark in 'benchmark/misc/function_call'. The modification adds an indicator of the average time of a "chatty" napi fun call (max 50M runs). This change will speed up chatty case 1.8x (overall), and will cut down the delay of napi mechanism to approx. 0.5x. Background: a simple C++ binding function (e.g. receiving little from JS, doing little and returning little to JS) is called 'chatty' case for JS<-->C++ fun call routine. This improvement also applies to getter/setter fun calls. PR-URL: #21072 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
This Pull Request updates dependency [node](https://github.com/nodejs/node) from `v10.4.1` to `v10.5.0` <details> <summary>Release Notes</summary> ### [`v10.5.0`](https://github.com/nodejs/node/releases/v10.5.0) [Compare Source](nodejs/node@v10.4.1...v10.5.0) ##### Notable Changes * **crypto**: * Support for `crypto.scrypt()` has been added. [#​20816](`https://github.com/nodejs/node/pull/20816`) * **fs**: * BigInt support has been added to `fs.stat` and `fs.watchFile`. [#​20220](`https://github.com/nodejs/node/pull/20220`) * APIs that take `mode` as arguments no longer throw on values larger than `0o777`. [#​20636](`https://github.com/nodejs/node/pull/20636`) [#​20975](`https://github.com/nodejs/node/pull/20975`) (Fixes: [#​20498](`https://github.com/nodejs/node/issues/20498`)) * Fix crashes in closed event watchers. [#​20985](`https://github.com/nodejs/node/pull/20985`) (Fixes: [#​20297](`https://github.com/nodejs/node/issues/20297`)) * **Worker Threads**: * Support for multi-threading has been added behind the `--experimental-worker` flag in the `worker_threads` module. This feature is *experimental* and may receive breaking changes at any time. [#​20876](`https://github.com/nodejs/node/pull/20876`) ##### Commits * [[`a6986fe8b6`](nodejs/node@a6986fe8b6)] - **async_hooks**: remove deprecated example (Mathias Buus) [#​20998](`https://github.com/nodejs/node/pull/20998`) * [[`4b9817bf1e`](nodejs/node@4b9817bf1e)] - **benchmark**: disable only the ESLint rule needing it (Rich Trott) [#​21133](`https://github.com/nodejs/node/pull/21133`) * [[`ecba1c57b1`](nodejs/node@ecba1c57b1)] - **(SEMVER-MINOR)** **benchmark**: port cluster/echo to worker (Timothy Gu) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`02adb2d62c`](nodejs/node@02adb2d62c)] - **(SEMVER-MINOR)** **build**: expose openssl scrypt functions to addons (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`c3fbac432f`](nodejs/node@c3fbac432f)] - **build**: install markdown linter for travis (Richard Lau) [#​21215](`https://github.com/nodejs/node/pull/21215`) * [[`896017b134`](nodejs/node@896017b134)] - **build**: build addon tests in parallel (Anna Henningsen) [#​21155](`https://github.com/nodejs/node/pull/21155`) * [[`76927fc734`](nodejs/node@76927fc734)] - **build**: stop distclean from deleting v8 files (Ujjwal Sharma) [#​21164](`https://github.com/nodejs/node/pull/21164`) * [[`b044256f2a`](nodejs/node@b044256f2a)] - **build**: use LC\_ALL of C for maximum compatibility (Rich Trott) [#​21222](`https://github.com/nodejs/node/pull/21222`) * [[`78c7d666fb`](nodejs/node@78c7d666fb)] - **build**: don't change locale on smartos (Refael Ackermann) [#​21220](`https://github.com/nodejs/node/pull/21220`) * [[`c688a00a6d`](nodejs/node@c688a00a6d)] - **build**: fix 'gas\_version' check on localized environments (Evandro Oliveira) [#​20394](`https://github.com/nodejs/node/pull/20394`) * [[`79b3423fb5`](nodejs/node@79b3423fb5)] - **build**: initial .travis.yml implementation (Anna Henningsen) [#​21059](`https://github.com/nodejs/node/pull/21059`) * [[`ea4be72f22`](nodejs/node@ea4be72f22)] - **child_process**: swallow errors in internal communication (Anatoli Papirovski) [#​21108](`https://github.com/nodejs/node/pull/21108`) * [[`9981220e2a`](nodejs/node@9981220e2a)] - **crypto**: fix behavior of createCipher in wrap mode (Tobias Nießen) [#​21287](`https://github.com/nodejs/node/pull/21287`) * [[`d0cb9cbb35`](nodejs/node@d0cb9cbb35)] - **(SEMVER-MINOR)** **crypto**: drop Math.pow(), use static exponentation (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`2d9c3cc89d`](nodejs/node@2d9c3cc89d)] - **(SEMVER-MINOR)** **crypto**: refactor randomBytes() (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`6262fa44d6`](nodejs/node@6262fa44d6)] - **(SEMVER-MINOR)** **crypto**: refactor pbkdf2() and pbkdf2Sync() methods (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`c9b4592dbf`](nodejs/node@c9b4592dbf)] - **(SEMVER-MINOR)** **crypto**: add scrypt() and scryptSync() methods (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`495756264a`](nodejs/node@495756264a)] - **(SEMVER-MINOR)** **crypto**: DRY type checking (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`e4a7e0d28b`](nodejs/node@e4a7e0d28b)] - **deps**: float ea7abee from openssl / CVE-2018-0732 (Rod Vagg) [#​21282](`https://github.com/nodejs/node/pull/21282`) * [[`0b90b071c4`](nodejs/node@0b90b071c4)] - **deps**: Upgrade node-inspect to 1.11.5 (Jan Krems) [#​21055](`https://github.com/nodejs/node/pull/21055`) * [[`ffc29c12da`](nodejs/node@ffc29c12da)] - **deps**: patch V8 to 6.7.288.46 (Myles Borins) [#​21260](`https://github.com/nodejs/node/pull/21260`) * [[`14bb905d18`](nodejs/node@14bb905d18)] - **deps**: V8: cherry-pick a440efb27f from upstream (Yang Guo) [#​21022](`https://github.com/nodejs/node/pull/21022`) * [[`65b9c427ac`](nodejs/node@65b9c427ac)] - **dns**: improve setServers() errors and performance (Jamie Davis) [#​20445](`https://github.com/nodejs/node/pull/20445`) * [[`bc20ec0c0f`](nodejs/node@bc20ec0c0f)] - **doc**: eliminate \_you\_ from N-API doc (Rich Trott) [#​21382](`https://github.com/nodejs/node/pull/21382`) * [[`318d6831bf`](nodejs/node@318d6831bf)] - **doc**: use imperative in COLLABORATOR\_GUIDE (Rich Trott) [#​21340](`https://github.com/nodejs/node/pull/21340`) * [[`177a7c06a8`](nodejs/node@177a7c06a8)] - **doc**: remove obsolete wiki references from BUILDING (Rich Trott) [#​21369](`https://github.com/nodejs/node/pull/21369`) * [[`15023df050`](nodejs/node@15023df050)] - **doc**: add davisjam to collaborators (Jamie Davis) [#​21273](`https://github.com/nodejs/node/pull/21273`) * [[`17c21b67ac`](nodejs/node@17c21b67ac)] - **doc**: fix indentation in console.md (Vse Mozhet Byt) [#​21367](`https://github.com/nodejs/node/pull/21367`) * [[`ef74368416`](nodejs/node@ef74368416)] - **doc**: fix heading of optional console method args (Michaël Zasso) [#​21311](`https://github.com/nodejs/node/pull/21311`) * [[`4f17841c20`](nodejs/node@4f17841c20)] - **doc**: use Class Method label consistently (Rich Trott) [#​21357](`https://github.com/nodejs/node/pull/21357`) * [[`4566ebacf4`](nodejs/node@4566ebacf4)] - **doc**: wrap style guide at 80 characters (Rich Trott) [#​21361](`https://github.com/nodejs/node/pull/21361`) * [[`6c41f33571`](nodejs/node@6c41f33571)] - **doc**: wrap pull-requests.md at 80 characters (Rich Trott) [#​21361](`https://github.com/nodejs/node/pull/21361`) * [[`b8213f17cc`](nodejs/node@b8213f17cc)] - **doc**: remove linking of url text to url (Rich Trott) [#​21361](`https://github.com/nodejs/node/pull/21361`) * [[`3f78220c2b`](nodejs/node@3f78220c2b)] - **doc**: correct styling of \_GitHub\_ in onboarding doc (Rich Trott) [#​21361](`https://github.com/nodejs/node/pull/21361`) * [[`9e994cb119`](nodejs/node@9e994cb119)] - **doc**: wrap releases.md at 80 chars (Rich Trott) [#​21361](`https://github.com/nodejs/node/pull/21361`) * [[`e00e5e6d5d`](nodejs/node@e00e5e6d5d)] - **doc**: switch the order of Writable and Readable (Joseph Gordon) [#​21333](`https://github.com/nodejs/node/pull/21333`) * [[`e1b571d6b7`](nodejs/node@e1b571d6b7)] - **doc**: make Deprecation cycle explanation more brief (Rich Trott) [#​21303](`https://github.com/nodejs/node/pull/21303`) * [[`df0f7a3b4d`](nodejs/node@df0f7a3b4d)] - **doc**: clarify async execute callback usage (Michael Dawson) [#​21217](`https://github.com/nodejs/node/pull/21217`) * [[`c5a65594ef`](nodejs/node@c5a65594ef)] - **doc**: move 5 collaborators to emeritus status (Rich Trott) [#​21272](`https://github.com/nodejs/node/pull/21272`) * [[`c1d53f86f8`](nodejs/node@c1d53f86f8)] - **doc**: update NODE\_OPTIONS section in cli.md (Vse Mozhet Byt) [#​21229](`https://github.com/nodejs/node/pull/21229`) * [[`13fd09bfa7`](nodejs/node@13fd09bfa7)] - **doc**: add build wg info to releases.md (Jon Moss) [#​21275](`https://github.com/nodejs/node/pull/21275`) * [[`0da910f9a5`](nodejs/node@0da910f9a5)] - **doc**: move Italo A. Casas to Release Emeritus (Myles Borins) [#​21315](`https://github.com/nodejs/node/pull/21315`) * [[`6f7de0b8d9`](nodejs/node@6f7de0b8d9)] - **doc**: trim deprecation level definition text (Rich Trott) [#​21241](`https://github.com/nodejs/node/pull/21241`) * [[`dd2fc90dcf`](nodejs/node@dd2fc90dcf)] - **doc**: fix reference to workerData in worker\_threads (Jeremiah Senkpiel) [#​21180](`https://github.com/nodejs/node/pull/21180`) * [[`5e46c16371`](nodejs/node@5e46c16371)] - **doc**: fix type in stream doc (Aliaksei Tuzik) [#​21178](`https://github.com/nodejs/node/pull/21178`) * [[`85dc9ac418`](nodejs/node@85dc9ac418)] - **doc**: add Michaël Zasso to Release team (Michaël Zasso) [#​21114](`https://github.com/nodejs/node/pull/21114`) * [[`5fa5ab6c48`](nodejs/node@5fa5ab6c48)] - **doc**: naming function as suggested in addon docs (Tommaso Allevi) [#​21067](`https://github.com/nodejs/node/pull/21067`) * [[`fe5d35123b`](nodejs/node@fe5d35123b)] - **(SEMVER-MINOR)** **doc**: document BigInt support in fs.Stats (Joyee Cheung) [#​20220](`https://github.com/nodejs/node/pull/20220`) * [[`2c4f80ffba`](nodejs/node@2c4f80ffba)] - **doc**: remove spaces around slashes (Rich Trott) [#​21140](`https://github.com/nodejs/node/pull/21140`) * [[`72e7e1da2d`](nodejs/node@72e7e1da2d)] - **doc**: alphabetize tls options (Rich Trott) [#​21139](`https://github.com/nodejs/node/pull/21139`) * [[`06ac81e786`](nodejs/node@06ac81e786)] - **doc**: streamline errors.md introductory material (Rich Trott) [#​21138](`https://github.com/nodejs/node/pull/21138`) * [[`73b8975b41`](nodejs/node@73b8975b41)] - **doc**: simplify deprecation language (Rich Trott) [#​21136](`https://github.com/nodejs/node/pull/21136`) * [[`6caa354377`](nodejs/node@6caa354377)] - **(SEMVER-MINOR)** **doc**: explain Worker semantics in async\_hooks.md (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`9f9355d6d2`](nodejs/node@9f9355d6d2)] - **doc**: fix inconsistent documentation (host vs hostname) (Davis Okoth) [#​20933](`https://github.com/nodejs/node/pull/20933`) * [[`a5c571424a`](nodejs/node@a5c571424a)] - **doc**: document file mode caveats on Windows (Joyee Cheung) [#​20636](`https://github.com/nodejs/node/pull/20636`) * [[`a75e44d135`](nodejs/node@a75e44d135)] - **esm**: ensure require.main for CJS top-level loads (Guy Bedford) [#​21150](`https://github.com/nodejs/node/pull/21150`) * [[`04e8f0749e`](nodejs/node@04e8f0749e)] - **(SEMVER-MINOR)** **fs**: support BigInt in fs.\*stat and fs.watchFile (Joyee Cheung) [#​20220](`https://github.com/nodejs/node/pull/20220`) * [[`c09bfd81b7`](nodejs/node@c09bfd81b7)] - **fs**: do not crash when using a closed fs event watcher (Joyee Cheung) [#​20985](`https://github.com/nodejs/node/pull/20985`) * [[`bacb2cb550`](nodejs/node@bacb2cb550)] - **fs**: refactor fs module (James M Snell) [#​20764](`https://github.com/nodejs/node/pull/20764`) * [[`db0bb5214a`](nodejs/node@db0bb5214a)] - **fs**: improve fchmod{Sync} validation (cjihrig) [#​20588](`https://github.com/nodejs/node/pull/20588`) * [[`2ffb9d6b5c`](nodejs/node@2ffb9d6b5c)] - **fs**: drop duplicate API in promises mode (Сковорода Никита Андреевич) [#​20559](`https://github.com/nodejs/node/pull/20559`) * [[`fc0b3610e2`](nodejs/node@fc0b3610e2)] - **fs**: don't limit ftruncate() length to 32 bits (cjihrig) [#​20851](`https://github.com/nodejs/node/pull/20851`) * [[`469baa062e`](nodejs/node@469baa062e)] - **fs**: add length validation to fs.truncate() (cjihrig) [#​20851](`https://github.com/nodejs/node/pull/20851`) * [[`6aade4a765`](nodejs/node@6aade4a765)] - **http**: remove a pair of outdated comments (Mark S. Everitt) [#​21214](`https://github.com/nodejs/node/pull/21214`) * [[`bcaf59c739`](nodejs/node@bcaf59c739)] - **http2**: fix memory leak for uncommon headers (Anna Henningsen) [#​21336](`https://github.com/nodejs/node/pull/21336`) * [[`dee250fd77`](nodejs/node@dee250fd77)] - **http2**: safer Http2Session destructor (Anatoli Papirovski) [#​21194](`https://github.com/nodejs/node/pull/21194`) * [[`296fd57324`](nodejs/node@296fd57324)] - **inspector**: stop dragging platform pointer (Eugene Ostroukhov) * [[`fb71337bdf`](nodejs/node@fb71337bdf)] - **(SEMVER-MINOR)** **lib**: rename checkIsArrayBufferView() (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`f3570f201b`](nodejs/node@f3570f201b)] - **(SEMVER-MINOR)** **lib**: replace checkUint() with validateInt32() (Ben Noordhuis) [#​20816](`https://github.com/nodejs/node/pull/20816`) * [[`b4b7d368be`](nodejs/node@b4b7d368be)] - **lib**: unmask mode\_t values with 0o777 (Joyee Cheung) [#​20975](`https://github.com/nodejs/node/pull/20975`) * [[`36e5100a39`](nodejs/node@36e5100a39)] - **lib**: support ranges in validateInt32() (cjihrig) [#​20588](`https://github.com/nodejs/node/pull/20588`) * [[`2fe88d2218`](nodejs/node@2fe88d2218)] - **lib**: mask mode\_t type of arguments with 0o777 (Joyee Cheung) [#​20636](`https://github.com/nodejs/node/pull/20636`) * [[`a0cfb0c9d4`](nodejs/node@a0cfb0c9d4)] - **lib**: add validateInteger() validator (cjihrig) [#​20851](`https://github.com/nodejs/node/pull/20851`) * [[`740d9f1a0e`](nodejs/node@740d9f1a0e)] - **lib,src**: make `StatWatcher` a `HandleWrap` (Anna Henningsen) [#​21244](`https://github.com/nodejs/node/pull/21244`) * [[`a657984109`](nodejs/node@a657984109)] - **lib,src**: remove openssl feature conditionals (Ben Noordhuis) [#​21094](`https://github.com/nodejs/node/pull/21094`) * [[`653b20b26d`](nodejs/node@653b20b26d)] - **loader**: remove unused error code in module\_job (Gus Caplan) [#​21354](`https://github.com/nodejs/node/pull/21354`) * [[`5d3dfedca2`](nodejs/node@5d3dfedca2)] - **meta**: remove CODEOWNERS (Rich Trott) [#​21161](`https://github.com/nodejs/node/pull/21161`) * [[`169bff3e9e`](nodejs/node@169bff3e9e)] - **n-api**: name CallbackBundle function fields (Anna Henningsen) [#​21240](`https://github.com/nodejs/node/pull/21240`) * [[`1dc9330b3a`](nodejs/node@1dc9330b3a)] - **n-api**: improve runtime perf of n-api func call (Kenny Yuan) [#​21072](`https://github.com/nodejs/node/pull/21072`) * [[`9047c8182c`](nodejs/node@9047c8182c)] - **n-api**: remove unused napi\_env member (Gabriel Schulhof) [#​21127](`https://github.com/nodejs/node/pull/21127`) * [[`18c057ab26`](nodejs/node@18c057ab26)] - **net**: emit 'close' when socket ends before connect (Brett Kiefer) [#​21290](`https://github.com/nodejs/node/pull/21290`) * [[`a3fd1cd8ea`](nodejs/node@a3fd1cd8ea)] - **perf_hooks**: remove less useful bootstrap marks (James M Snell) [#​21247](`https://github.com/nodejs/node/pull/21247`) * [[`8fddf591c5`](nodejs/node@8fddf591c5)] - **perf_hooks**: set bootstrap complete in only one place (James M Snell) [#​21247](`https://github.com/nodejs/node/pull/21247`) * [[`fc2956d37a`](nodejs/node@fc2956d37a)] - **process**: backport process/methods file (Michaël Zasso) [#​21172](`https://github.com/nodejs/node/pull/21172`) * [[`78ad4e9dde`](nodejs/node@78ad4e9dde)] - **src**: remove unused argc var in node\_stat\_watcher (Daniel Bevenius) [#​21337](`https://github.com/nodejs/node/pull/21337`) * [[`7fa1344143`](nodejs/node@7fa1344143)] - **src**: use `%zx` in printf for size\_t (Anna Henningsen) [#​21323](`https://github.com/nodejs/node/pull/21323`) * [[`671346ee8f`](nodejs/node@671346ee8f)] - **src**: do proper error checking in `AsyncWrap::MakeCallback` (Anna Henningsen) [#​21189](`https://github.com/nodejs/node/pull/21189`) * [[`aa468abc4c`](nodejs/node@aa468abc4c)] - **src**: unify native symbol inspection code (Anna Henningsen) [#​21238](`https://github.com/nodejs/node/pull/21238`) * [[`e92b89a75d`](nodejs/node@e92b89a75d)] - **src**: fix http2 typos (Anatoli Papirovski) [#​21194](`https://github.com/nodejs/node/pull/21194`) * [[`4f01168414`](nodejs/node@4f01168414)] - **src**: do not persist fs\_poll handle in stat\_watcher (Anatoli Papirovski) [#​21093](`https://github.com/nodejs/node/pull/21093`) * [[`685b9b2a6a`](nodejs/node@685b9b2a6a)] - **src**: do not persist timer handle in cares\_wrap (Anatoli Papirovski) [#​21093](`https://github.com/nodejs/node/pull/21093`) * [[`4757771db3`](nodejs/node@4757771db3)] - **src**: add consistency check to node\_platform.cc (Anna Henningsen) [#​21156](`https://github.com/nodejs/node/pull/21156`) * [[`8e2e16721b`](nodejs/node@8e2e16721b)] - **src**: add node\_encoding.cc (James M Snell) [#​21112](`https://github.com/nodejs/node/pull/21112`) * [[`39b38754eb`](nodejs/node@39b38754eb)] - **src**: cleanup beforeExit for consistency (James M Snell) [#​21113](`https://github.com/nodejs/node/pull/21113`) * [[`314b47d1cf`](nodejs/node@314b47d1cf)] - **(SEMVER-MINOR)** **src**: add Env::profiler\_idle\_notifier\_started() (Timothy Gu) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`5209ff9562`](nodejs/node@5209ff9562)] - **(SEMVER-MINOR)** **src**: remove unused fields msg\_ and env\_ (Daniel Bevenius) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`9a734132f9`](nodejs/node@9a734132f9)] - **(SEMVER-MINOR)** **src**: make handle onclose property a Symbol (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`e6f06807b1`](nodejs/node@e6f06807b1)] - **(SEMVER-MINOR)** **src**: simplify handle closing (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`65924c70e8`](nodejs/node@65924c70e8)] - **(SEMVER-MINOR)** **src**: remove unused fields isolate\_ (Daniel Bevenius) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`de7403f813`](nodejs/node@de7403f813)] - **(SEMVER-MINOR)** **src**: cleanup per-isolate state on platform on isolate unregister (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`ba17c9e46b`](nodejs/node@ba17c9e46b)] - **src**: refactor bootstrap to use bootstrap object (James M Snell) [#​20917](`https://github.com/nodejs/node/pull/20917`) * [[`cbdc1fdf44`](nodejs/node@cbdc1fdf44)] - **src, tools**: add check for left leaning pointers (Daniel Bevenius) [#​21010](`https://github.com/nodejs/node/pull/21010`) * [[`935309325b`](nodejs/node@935309325b)] - **test**: fix deprecation warning due to util.print (Tobias Nießen) [#​21265](`https://github.com/nodejs/node/pull/21265`) * [[`d7ba75f8aa`](nodejs/node@d7ba75f8aa)] - **test**: add test to check colorMode type of Console (Masashi Hirano) [#​21248](`https://github.com/nodejs/node/pull/21248`) * [[`0b00172df8`](nodejs/node@0b00172df8)] - **test**: removing unnecessary parameter from assert call (djmgit) [#​21307](`https://github.com/nodejs/node/pull/21307`) * [[`dea3ac7bff`](nodejs/node@dea3ac7bff)] - **test**: improve statwatcher async\_hooks test (Anna Henningsen) [#​21244](`https://github.com/nodejs/node/pull/21244`) * [[`792335f712`](nodejs/node@792335f712)] - **test**: add workerdata-sharedarraybuffer test (Jeremiah Senkpiel) [#​21180](`https://github.com/nodejs/node/pull/21180`) * [[`e8d15cb149`](nodejs/node@e8d15cb149)] - **test**: mark test-inspector-port-zero-cluster flaky (Rich Trott) [#​21251](`https://github.com/nodejs/node/pull/21251`) * [[`688bdfef7f`](nodejs/node@688bdfef7f)] - **test**: add crypto check to test-http2-debug (Daniel Bevenius) [#​21205](`https://github.com/nodejs/node/pull/21205`) * [[`2270ab2a12`](nodejs/node@2270ab2a12)] - **test**: remove string literals from assert.strictEqual() calls (James Kylstra) [#​21211](`https://github.com/nodejs/node/pull/21211`) * [[`187951c0fc`](nodejs/node@187951c0fc)] - **test**: move inspector-stress-http to sequential (Rich Trott) [#​21227](`https://github.com/nodejs/node/pull/21227`) * [[`bda34ea203`](nodejs/node@bda34ea203)] - **test**: check gc does not resurrect the loop (Anatoli Papirovski) [#​21093](`https://github.com/nodejs/node/pull/21093`) * [[`4d782c4720`](nodejs/node@4d782c4720)] - **test**: improve assert error messages (Hristijan Gjorgjievski) [#​21160](`https://github.com/nodejs/node/pull/21160`) * [[`2655c7b194`](nodejs/node@2655c7b194)] - **test**: mark fs-readfile-tostring-fail flaky for all (Rich Trott) [#​21177](`https://github.com/nodejs/node/pull/21177`) * [[`17954c2b01`](nodejs/node@17954c2b01)] - **test**: improve internal/buffer.js test coverage (Masashi Hirano) [#​21061](`https://github.com/nodejs/node/pull/21061`) * [[`2ff4704447`](nodejs/node@2ff4704447)] - **test**: move test-readuint to test-buffer-readuint (Michaël Zasso) [#​21170](`https://github.com/nodejs/node/pull/21170`) * [[`9c3a7bf076`](nodejs/node@9c3a7bf076)] - **test**: make url-util-format engine agnostic (Rich Trott) [#​21141](`https://github.com/nodejs/node/pull/21141`) * [[`3d8ec8f85c`](nodejs/node@3d8ec8f85c)] - **test**: make url-parse-invalid-input engine agnostic (Rich Trott) [#​21132](`https://github.com/nodejs/node/pull/21132`) * [[`0b0370f884`](nodejs/node@0b0370f884)] - **test**: remove unref in http2 test (Anatoli Papirovski) [#​21145](`https://github.com/nodejs/node/pull/21145`) * [[`14a017cf8d`](nodejs/node@14a017cf8d)] - **test**: apply promises API to fourth appendFile test (Rich Trott) [#​21131](`https://github.com/nodejs/node/pull/21131`) * [[`aa9dbf666b`](nodejs/node@aa9dbf666b)] - **test**: apply promises API to fourth appendFile test (Rich Trott) [#​21131](`https://github.com/nodejs/node/pull/21131`) * [[`185b9e45d3`](nodejs/node@185b9e45d3)] - **test**: apply promises API to third appendFile test (Rich Trott) [#​21131](`https://github.com/nodejs/node/pull/21131`) * [[`c400448e85`](nodejs/node@c400448e85)] - **test**: improve debug output in trace-events test (Rich Trott) [#​21120](`https://github.com/nodejs/node/pull/21120`) * [[`a4ad9891e3`](nodejs/node@a4ad9891e3)] - **test**: add test for Linux perf (Matheus Marchini) [#​20783](`https://github.com/nodejs/node/pull/20783`) * [[`e16036c462`](nodejs/node@e16036c462)] - **test**: create new directory v8-updates (Matheus Marchini) [#​20783](`https://github.com/nodejs/node/pull/20783`) * [[`93ce63c89f`](nodejs/node@93ce63c89f)] - **(SEMVER-MINOR)** **test**: add test against unsupported worker features (Timothy Gu) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`94dcdfb898`](nodejs/node@94dcdfb898)] - **test**: increase coverage for fs.promises.truncate (Masashi Hirano) [#​20638](`https://github.com/nodejs/node/pull/20638`) * [[`c9cee63179`](nodejs/node@c9cee63179)] - **test,tools**: refactor custom ESLint for readability (Rich Trott) [#​21134](`https://github.com/nodejs/node/pull/21134`) * [[`ed05d9a821`](nodejs/node@ed05d9a821)] - **(SEMVER-MINOR)** **test,tools**: enable running tests under workers (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`6285fe94f6`](nodejs/node@6285fe94f6)] - **tools**: do not disable `quotes` rule in .eslintrc.js (Rich Trott) [#​21338](`https://github.com/nodejs/node/pull/21338`) * [[`98346de08c`](nodejs/node@98346de08c)] - **tools**: lint doc/\*.md files (Rich Trott) [#​21361](`https://github.com/nodejs/node/pull/21361`) * [[`521f8f1d95`](nodejs/node@521f8f1d95)] - **tools**: add BigInt64Array and BigUint64Array to globals (Joyee Cheung) [#​21255](`https://github.com/nodejs/node/pull/21255`) * [[`a5c386d1ba`](nodejs/node@a5c386d1ba)] - **tools**: add option to use custom template with js2c.py (Shelley Vohr) [#​21187](`https://github.com/nodejs/node/pull/21187`) * [[`7f70fe83ef`](nodejs/node@7f70fe83ef)] - **tools**: add BigInt to globals (Nikolai Vavilov) [#​21237](`https://github.com/nodejs/node/pull/21237`) * [[`4e742e379b`](nodejs/node@4e742e379b)] - **tools**: update tooling to work with new macOS CLI … (Rich Trott) [#​21173](`https://github.com/nodejs/node/pull/21173`) * [[`ed2b57bcd5`](nodejs/node@ed2b57bcd5)] - **tools**: remove unused global types from type-parser (Rich Trott) [#​21135](`https://github.com/nodejs/node/pull/21135`) * [[`d46446afc5`](nodejs/node@d46446afc5)] - **v8**: replace Buffer with FastBuffer in deserialize (Ujjwal Sharma) [#​21196](`https://github.com/nodejs/node/pull/21196`) * [[`917960e0a1`](nodejs/node@917960e0a1)] - **win, build**: add documentation support to vcbuild (Bartosz Sosnowski) [#​19663](`https://github.com/nodejs/node/pull/19663`) * [[`03fbc9e749`](nodejs/node@03fbc9e749)] - **(SEMVER-MINOR)** **worker**: rename to worker\_threads (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`9ad42b766e`](nodejs/node@9ad42b766e)] - **(SEMVER-MINOR)** **worker**: improve error (de)serialization (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`6b1a887aa2`](nodejs/node@6b1a887aa2)] - **(SEMVER-MINOR)** **worker**: enable stdio (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`c97fb91e55`](nodejs/node@c97fb91e55)] - **(SEMVER-MINOR)** **worker**: restrict supported extensions (Timothy Gu) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`109c92e8fa`](nodejs/node@109c92e8fa)] - **(SEMVER-MINOR)** **worker**: initial implementation (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`d1f372f052`](nodejs/node@d1f372f052)] - **(SEMVER-MINOR)** **worker**: add `SharedArrayBuffer` sharing (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`f447acd87b`](nodejs/node@f447acd87b)] - **(SEMVER-MINOR)** **worker**: support MessagePort passing in messages (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`337be58ee6`](nodejs/node@337be58ee6)] - **(SEMVER-MINOR)** **worker**: implement `MessagePort` and `MessageChannel` (Anna Henningsen) [#​20876](`https://github.com/nodejs/node/pull/20876`) * [[`4a54ebc3bd`](nodejs/node@4a54ebc3bd)] - **worker,src**: display remaining handles if `uv\_loop\_close` fails (Anna Henningsen) [#​21238](`https://github.com/nodejs/node/pull/21238`) * [[`529d24e3e8`](nodejs/node@529d24e3e8)] - ***Revert*** "**workers,trace_events**: set thread name for workers" (James M Snell) [#​21363](`https://github.com/nodejs/node/pull/21363`) * [[`dfb5cf6963`](nodejs/node@dfb5cf6963)] - **workers,trace_events**: set thread name for workers (James M Snell) [#​21246](`https://github.com/nodejs/node/pull/21246`) --- </details> --- This PR has been generated by [Renovate Bot](https://renovatebot.com).
Update: I did a small experiment and the preliminary data show that CC @addaleax |
@kenny-y That’s good to know, thanks for investigating :) |
Added a new struct CallbackBundle to eliminate all GetInternalField() calls. The principle is to store all required data inside a C++ struct, and then store the pointer in the JavaScript object. Before this change, the required data are stored in the JavaScript object in 3 or 4 seperate pointers. For every napi fun call, 3 of them have to be fetched out, which are 3 GetInternalField() calls; after this change, the C++ struct will be directly fetched out by using v8::External::Value(), which is faster. Profiling data show that GetInternalField() is slow. On an i7-4770K (3.50GHz) box, a C++ V8-binding fun call is 8 ns, before this change, napi fun call is 36 ns; after this change, napi fun call is 20 ns. The above data are measured using a modified benchmark in 'benchmark/misc/function_call'. The modification adds an indicator of the average time of a "chatty" napi fun call (max 50M runs). This change will speed up chatty case 1.8x (overall), and will cut down the delay of napi mechanism to approx. 0.5x. Background: a simple C++ binding function (e.g. receiving little from JS, doing little and returning little to JS) is called 'chatty' case for JS<-->C++ fun call routine. This improvement also applies to getter/setter fun calls. PR-URL: nodejs#21072 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
Added a new struct CallbackBundle to eliminate all GetInternalField() calls. The principle is to store all required data inside a C++ struct, and then store the pointer in the JavaScript object. Before this change, the required data are stored in the JavaScript object in 3 or 4 seperate pointers. For every napi fun call, 3 of them have to be fetched out, which are 3 GetInternalField() calls; after this change, the C++ struct will be directly fetched out by using v8::External::Value(), which is faster. Profiling data show that GetInternalField() is slow. On an i7-4770K (3.50GHz) box, a C++ V8-binding fun call is 8 ns, before this change, napi fun call is 36 ns; after this change, napi fun call is 20 ns. The above data are measured using a modified benchmark in 'benchmark/misc/function_call'. The modification adds an indicator of the average time of a "chatty" napi fun call (max 50M runs). This change will speed up chatty case 1.8x (overall), and will cut down the delay of napi mechanism to approx. 0.5x. Background: a simple C++ binding function (e.g. receiving little from JS, doing little and returning little to JS) is called 'chatty' case for JS<-->C++ fun call routine. This improvement also applies to getter/setter fun calls. Backport-PR-URL: #21733 PR-URL: #21072 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
Added a new struct CallbackBundle to eliminate all GetInternalField() calls. The principle is to store all required data inside a C++ struct, and then store the pointer in the JavaScript object. Before this change, the required data are stored in the JavaScript object in 3 or 4 seperate pointers. For every napi fun call, 3 of them have to be fetched out, which are 3 GetInternalField() calls; after this change, the C++ struct will be directly fetched out by using v8::External::Value(), which is faster. Profiling data show that GetInternalField() is slow. On an i7-4770K (3.50GHz) box, a C++ V8-binding fun call is 8 ns, before this change, napi fun call is 36 ns; after this change, napi fun call is 20 ns. The above data are measured using a modified benchmark in 'benchmark/misc/function_call'. The modification adds an indicator of the average time of a "chatty" napi fun call (max 50M runs). This change will speed up chatty case 1.8x (overall), and will cut down the delay of napi mechanism to approx. 0.5x. Background: a simple C++ binding function (e.g. receiving little from JS, doing little and returning little to JS) is called 'chatty' case for JS<-->C++ fun call routine. This improvement also applies to getter/setter fun calls. Backport-PR-URL: #21733 PR-URL: #21072 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
napi: improve runtime performance of every napi fun call.
Added a new struct CallbackBundle to eliminate all
GetInternalField() calls.
The principle is to store all required data inside a C++ struct,
and then store the pointer in the JavaScript object. Before this
change, the required data are stored in the JavaScript object in
3 or 4 seperate pointers. For every napi fun call, 3 of them
have to be fetched out, which are 3 GetInternalField() calls;
after this change, the C++ struct will be directly fetched out
by using v8::External::Value(), which is faster.
Profiling data show that GetInternalField() is slow.
On an i7-4770K (3.50GHz) box, a C++ V8-binding fun call is 8 ns,
before this change, napi fun call is 36 ns; after this change,
napi fun call is 20 ns.
The above data are measured using a modified benchmark in
'benchmark/misc/function_call'. The modification adds an indicator
of the average time of a "chatty" napi fun call (max 50M runs).
This change will speed up chatty case 1.8x (overall), and will cut
down the delay of napi mechanism to approx. 0.5x.
Background: a simple C++ binding function (e.g. receiving little
from JS, doing little and returning little to JS) is called
'chatty' case for JS<-->C++ fun call routine.
This improvement also applies to getter/setter fun calls.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes