-
Notifications
You must be signed in to change notification settings - Fork 34
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
optimize passing arguments from js to c #327
Comments
Thanks @gabrielschulhof, I see that you asserted that overflow happens when calling What I meant was that if the JS value is more than 32 bits, I would have expected an exception to be thrown instead. However, this kind of check should rather be in
Yes, I thought of this but the addon needs to be zero-copy, and the
I am using N-API directly, using Thanks for all your help with this! |
I know we always compare N-API to v8, but is there any chance that some of the v8 methods we're comparing against are slower than they should be? |
@jorangreef when I build the comparison binding in V8 I try to use the most efficient method for grabbing the arguments from the engine. |
@jorangreef have you tried switching from |
I tested some more combinations, and it looks like if you switch to @nodejs/addon-api this supports that we should provide validation-free versions of the convert-to-native-type APIs. |
Sorry I could look at the code, but for clarity in this issue, what do you mean by "validation-free" |
@mhdawson by "validation-free" I mean a version of the API where we don't call APIs such as Similarly, we do not validate that the We leave the validation (if any) to the addon author and document that the API doesn't perform any validation, all in the name of better performance. |
@mhdawson I ran individual benchmarks for each data type to test whether removing the validation would improve the performance to some significance, but the only data type for which this was the case was I suspect that's because in if (val->IsInt32()) {
*result = val.As<v8::Int32>()->Value();
return napi_clear_last_error(env);
}
RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
// v8::Value::IntegerValue() converts NaN, +Inf, and -Inf to INT64_MIN,
// inconsistent with v8::Value::Int32Value() which converts those values to 0.
// Special-case all non-finite values to match that behavior.
double doubleValue = val.As<v8::Number>()->Value();
if (std::isfinite(doubleValue)) {
// Empty context: https://github.com/nodejs/node/issues/14379
v8::Local<v8::Context> context;
*result = val->IntegerValue(context).FromJust();
} else {
*result = 0;
} the performance gain stems from reducing all this to just *result = val->IntegerValue(context).FromJust(); foregoing the special-casing mentioned in the comment. So, a new, non-validating API really only makes sense for Int64: |
Thanks @gabrielschulhof for the tremendous effort. |
@gabrielschulhof thanks for all of the analysis. One last question, Did you check the perf if this part is left in
|
@mhdawson we can leave it in. It has no perf impact. |
Adds `napi_get_value_int64_unsafe()` which skips the correction whereby non-finite values are rendered as zero, exposing instead the engine-specific behavior. This tradeoff favors performance-intensive applications where guarantees of finiteness can be made a priori. This modification is further motivated by the fact that there is currently no typed array support for `int64_t`. Fixes: nodejs/abi-stable-node#327
Looks like the related PR has landed. Closing. |
See #55 (comment) for context.
The text was updated successfully, but these errors were encountered: