Skip to content

Commit e136bd8

Browse files
authored
perf(napi): optimize primitive napi functions (#16163)
This optimization applies on `napi_get_undefined`, `napi_get_null` & `napi_get_boolean`. ``` # main benchmark time (avg) (min … max) p75 p99 p995 ---------------------------------------------------------- ----------------------------- warmup 482.55 ps/iter (462.5 ps … 15.67 ns) 475 ps 525 ps 829.1 ps napi_get_undefined 25.07 ns/iter (24.03 ns … 36.87 ns) 25.37 ns 27.09 ns 34.85 ns ``` ``` # This patch benchmark time (avg) (min … max) p75 p99 p995 ---------------------------------------------------------- ----------------------------- warmup 484.78 ps/iter (462.5 ps … 14.4 ns) 475 ps 554.1 ps 583.3 ps napi_get_undefined 15.52 ns/iter (15.35 ns … 22.14 ns) 15.41 ns 17.18 ns 20.02 ns ```
1 parent be80c57 commit e136bd8

File tree

7 files changed

+49
-4
lines changed

7 files changed

+49
-4
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ opt-level = 3
159159
opt-level = 3
160160
[profile.release.package.deno_napi]
161161
opt-level = 3
162+
[profile.release.package.test_napi]
163+
opt-level = 3
162164
[profile.release.package.num-bigint-dig]
163165
opt-level = 3
164166
[profile.release.package.v8]

cli/bench/napi/bench.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { loadTestLibrary } from "../../../test_napi/common.js";
2+
3+
const lib = loadTestLibrary();
4+
5+
Deno.bench("warmup", () => {});
6+
Deno.bench("napi_get_undefined", () => lib.test_get_undefined(0));

cli/bench/napi/bench_node.mjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { run, bench } from "mitata";
2+
import { createRequire } from "module";
3+
4+
const require = createRequire(import.meta.url);
5+
const lib = require("../../../test_napi.node");
6+
7+
bench("warmup", () => {});
8+
bench("napi_get_undefined", () => lib.test_get_undefined(0));
9+
10+
run();

cli/napi/js_native_api.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,7 @@ fn napi_get_boolean(
13331333
) -> Result {
13341334
let env: &mut Env = env.as_mut().ok_or(Error::InvalidArg)?;
13351335
let value: v8::Local<v8::Value> =
1336-
v8::Boolean::new(&mut env.scope(), value).into();
1336+
v8::Boolean::new(env.isolate(), value).into();
13371337
*result = value.into();
13381338
Ok(())
13391339
}
@@ -1520,7 +1520,7 @@ fn napi_get_new_target(
15201520
fn napi_get_null(env: *mut Env, result: *mut napi_value) -> Result {
15211521
let env: &mut Env = env.as_mut().ok_or(Error::InvalidArg)?;
15221522

1523-
let value: v8::Local<v8::Value> = v8::null(&mut env.scope()).into();
1523+
let value: v8::Local<v8::Value> = v8::null(env.isolate()).into();
15241524
*result = value.into();
15251525
Ok(())
15261526
}
@@ -1611,7 +1611,7 @@ fn napi_get_typedarray_info(
16111611
#[napi_sym::napi_sym]
16121612
fn napi_get_undefined(env: *mut Env, result: *mut napi_value) -> Result {
16131613
let env: &mut Env = env.as_mut().ok_or(Error::InvalidArg)?;
1614-
let value: v8::Local<v8::Value> = v8::undefined(&mut env.scope()).into();
1614+
let value: v8::Local<v8::Value> = v8::undefined(env.isolate()).into();
16151615
*result = value.into();
16161616
Ok(())
16171617
}

serde_v8/ser.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use serde::ser;
33
use serde::ser::Serialize;
44

55
use std::cell::RefCell;
6+
use std::ops::DerefMut;
67

78
use crate::error::{Error, Result};
89
use crate::keys::v8_struct_key;
@@ -435,7 +436,8 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> {
435436
}
436437

437438
fn serialize_f64(self, v: f64) -> JsResult<'a> {
438-
Ok(v8::Number::new(&mut self.scope.borrow_mut(), v).into())
439+
let scope = &mut self.scope.borrow_mut();
440+
Ok(v8::Number::new(scope.deref_mut(), v).into())
439441
}
440442

441443
fn serialize_bool(self, v: bool) -> JsResult<'a> {

test_napi/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod callback;
1010
pub mod coerce;
1111
pub mod numbers;
1212
pub mod object_wrap;
13+
pub mod primitives;
1314
pub mod promise;
1415
pub mod properties;
1516
pub mod strings;
@@ -67,6 +68,7 @@ unsafe extern "C" fn napi_register_module_v1(
6768
numbers::init(env, exports);
6869
typedarray::init(env, exports);
6970
array::init(env, exports);
71+
primitives::init(env, exports);
7072
properties::init(env, exports);
7173
promise::init(env, exports);
7274
coerce::init(env, exports);

test_napi/src/primitives.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use napi_sys::*;
2+
use std::ptr;
3+
4+
extern "C" fn test_get_undefined(
5+
env: napi_env,
6+
_: napi_callback_info,
7+
) -> napi_value {
8+
let mut result = ptr::null_mut();
9+
unsafe { napi_get_undefined(env, &mut result) };
10+
result
11+
}
12+
13+
pub fn init(env: napi_env, exports: napi_value) {
14+
let properties = &[crate::new_property!(
15+
env,
16+
"test_get_undefined\0",
17+
test_get_undefined
18+
)];
19+
20+
unsafe {
21+
napi_define_properties(env, exports, properties.len(), properties.as_ptr())
22+
};
23+
}

0 commit comments

Comments
 (0)