Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.4k
benchmark: add n-api function arguments benchmark suite#21555
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
This benchmark suite is added to measure the performance of n-api function call with various type/number of arguments. The cases in this suite are carefully selected to efficiently show the performance trend.
kenny-y commented Jun 27, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
The below charts are generated by this benchmark suite: Generally speaking, it's better to cover more combination of types and numbers of arguments, but from my observation, the trend is the same. So I filtered out most of the combination and selected the cases. |
gabrielschulhof commented Jun 27, 2018
@kenny-y I think it might be better placed under I'm surprised that N-API performs better in some use cases than V8. It seems strange. |
| status = napi_create_string_utf8(env, "reduce", strlen("reduce"), &key); | ||
| assert(status == napi_ok); | ||
| status = napi_get_property(env, args[0], key, &value); | ||
| assert(status == napi_ok); |
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 could combine these into napi_get_named_property(). That will internally create the string for you.
| status = napi_typeof(env, args[0], types); | ||
| assert(status == napi_ok); | ||
| assert(types[0] == napi_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.
You should add && argc == 1 into the assertion, to be on par with the V8 version.
| v8::Isolate* isolate = args.GetIsolate(); | ||
| assert(args.Length() == 1 && args[0]->IsObject()); | ||
| if (args.Length() == 1 && args[0]->IsObject()){ |
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.
I think it might be best to save the result of args.Length() == 1 && args[0]->IsObject() first and then both assert() it and use it as the if-statement condition. For clarity, you could assert(argumentsCorrect && "argument length is 1 and the first argument is an object"), where bool argumentsCorrect = (args.Length() == 1 && args[0]->IsObject());
gabrielschulhof commented Jun 27, 2018
Wait, NM. |
| Local<Value> map = obj->Get(String::NewFromUtf8(isolate, "map")); | ||
| Local<Value> operand = obj->Get(String::NewFromUtf8(isolate, "operand")); | ||
| Local<Value> data = obj->Get(String::NewFromUtf8(isolate, "data")); | ||
| Local<Value> reduce = obj->Get(String::NewFromUtf8(isolate, "reduce")); |
gabrielschulhofJun 27, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
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.
N-API uses the maybe version of Get() and String::NewFromUtf8() because the others are deprecated, so, these should be changed to
Local<Context> context = isolate->GetCurrentContext();and then, for each property,
MaybeLocal<String> map_string = String::NewFromUtf8(isolate, "map", NewStringType::kNormal); assert(!map_string.IsEmpty()); MaybeLocal<value> maybe_map = obj->Get(context, map_string.ToLocalChecked()); assert(!maybe_map.IsEmpty()); Local<Value> map = maybe_map.ToLocalChecked();kenny-y commented Jun 28, 2018
Yep, there was a PR #21046 moved After the change to |
mhdawson commented Jun 29, 2018
@kenny-y thanks for creating this. I won't have time to take a good look until at least next week but looks like @gabrielschulhof is already commenting :) |
gabrielschulhof left a comment • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
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.
| const getArgs = (type) =>{ | ||
| return generateArgs(type.split('-')[1]); | ||
| }; |
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 this function if you use multiple parameters (see below).
| ['v8', 'napi'].forEach((type) =>{ | ||
| benchTypes.push(type + '-' + arg); | ||
| }); | ||
| }); |
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 benchTypes either if you use multiple parameters (see below).
| }); | ||
| const bench = common.createBenchmark(main,{ | ||
| type: benchTypes, |
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.
Instead of benchTypes use argsTypes directly, and add a second parameter
engine: ['v8','napi'],| n: [1, 1e1, 1e2, 1e3, 1e4, 1e5], | ||
| }); | ||
| function main({n, type }){ |
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.
Make this {n, engine, type}, and then you don't need to concatenate or split the arguments. The benchmark will generate all combinations of the three arguments.
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.
Good to know. Thanks 👍
gabrielschulhof commented Jul 1, 2018
@kenny-y could you please also resolve the warnings? |
kenny-y commented Jul 3, 2018
@mhdawson Thanks. My original purpose to create this benchmark was to find optimization opportunities, like the previous one #21072, but none had been identified yet... @gabrielschulhof helped me a lot on the previous one, as well as this PR 👍 👍 👍 |
gabrielschulhof left a comment
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.
LGTM
| assert(status == napi_ok); \ | ||
| status = napi_set_named_property(env, exports, name, func ## _v); \ | ||
| assert(status == napi_ok); \ | ||
| } while (0); |
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: The trailing backslashes must be aligned to the column of the outermost trailing backslash.
gabrielschulhof commented Jul 3, 2018
| #define EXPORT_FUNC(name, func) \ | ||
| do{\ | ||
| napi_value func ## _v; \ |
gabrielschulhofJul 4, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
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.
Actually, you can safely declare
napi_status status; napi_value js_func;here and pass js_func to napi_create_function() and napi_set_named_property() because the do{... } while (0) scope protects them, and then each invocation of the macro is self-contained. Then there's no need to func ## _v, nor to assume that napi_status status is declared outside the macro.
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.
Oh, and please pass exports into the macro as a parameter, and put brackets around env, exports, and func when you use them inside the macro.
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.
Done :)
| NULL, \ | ||
| &js_func); \ | ||
| assert(status == napi_ok); \ | ||
| status = napi_set_named_property((env), \ |
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: Align arguments as with the previous call.
gabrielschulhof commented Jul 5, 2018
gabrielschulhof commented Jul 5, 2018
mhdawson commented Jul 5, 2018
Since @kfarnung beat me to it I'm happy to leave it at that :) |
gabrielschulhof commented Jul 6, 2018
Landed in 3314b3a. |
This benchmark suite is added to measure the performance of n-api function call with various type/number of arguments. The cases in this suite are carefully selected to efficiently show the performance trend. PR-URL: #21555 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Kyle Farnung <[email protected]>
This benchmark suite is added to measure the performance of n-api function call with various type/number of arguments. The cases in this suite are carefully selected to efficiently show the performance trend. PR-URL: #21555 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Kyle Farnung <[email protected]>










This benchmark suite is added to measure the performance of n-api
function call with various type/number of arguments. The cases in
this suite are carefully selected to efficiently show the performance
trend.
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes