Merge pull request #558 from napi-rs/bench-array

bench: add array suite
This commit is contained in:
LongYinan 2021-05-17 11:52:33 +08:00 committed by GitHub
commit 07a60125d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 142 additions and 24 deletions

View file

@ -8,8 +8,10 @@ version = "0.1.0"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
napi = {path = "../napi", features = ["napi4"]} napi = {path = "../napi", features = ["napi4", "serde-json"]}
napi-derive = {path = "../napi-derive"} napi-derive = {path = "../napi-derive"}
serde = "1"
serde_json = "1"
[target.'cfg(all(unix, not(target_env = "musl"), not(target_arch = "aarch64")))'.dependencies] [target.'cfg(all(unix, not(target_env = "musl"), not(target_arch = "aarch64")))'.dependencies]
jemallocator = {version = "0.3", features = ["disable_initial_exec_tls"]} jemallocator = {version = "0.3", features = ["disable_initial_exec_tls"]}

View file

@ -5,6 +5,8 @@ import { Summary } from 'benny/lib/internal/common-types'
import { benchAsync } from './async' import { benchAsync } from './async'
import { benchBuffer } from './buffer' import { benchBuffer } from './buffer'
import { benchCreateArray } from './create-array'
import { benchGetArray } from './get-array-from-js'
import { benchGetSetProperty } from './get-set-property' import { benchGetSetProperty } from './get-set-property'
import { benchNoop } from './noop' import { benchNoop } from './noop'
import { benchPlus } from './plus' import { benchPlus } from './plus'
@ -14,6 +16,8 @@ async function run() {
await benchNoop(), await benchNoop(),
await benchPlus(), await benchPlus(),
await benchBuffer(), await benchBuffer(),
await benchCreateArray(),
await benchGetArray(),
await benchGetSetProperty(), await benchGetSetProperty(),
await benchAsync(), await benchAsync(),
] ]

25
bench/create-array.ts Normal file
View file

@ -0,0 +1,25 @@
import b from 'benny'
const {
createArrayJson,
createArray,
createArrayWithSerdeTrait,
} = require('./index.node')
export const benchCreateArray = () =>
b.suite(
'createArray',
b.add('createArrayJson', () => {
JSON.parse(createArrayJson())
}),
b.add('create array for loop', () => {
createArray()
}),
b.add('create array with serde trait', () => {
createArrayWithSerdeTrait()
}),
b.cycle(),
b.complete(),
)

View file

@ -0,0 +1,27 @@
import b from 'benny'
const {
getArrayFromJson,
getArrayFromJsArray,
getArrayWithForLoop,
} = require('./index.node')
const FIXTURE = Array.from({ length: 1000 }).fill(42)
export const benchGetArray = () =>
b.suite(
'getArrayFromJs',
b.add('get array from json string', () => {
getArrayFromJson(JSON.stringify(FIXTURE))
}),
b.add('get array from serde', () => {
getArrayFromJsArray(FIXTURE)
}),
b.add('get array with for loop', () => {
getArrayWithForLoop(FIXTURE)
}),
b.cycle(),
b.complete(),
)

32
bench/src/create_array.rs Normal file
View file

@ -0,0 +1,32 @@
use napi::{ContextlessResult, Env, JsObject, JsString, JsUnknown, Result};
use serde_json::to_string;
pub fn register_js(exports: &mut JsObject) -> Result<()> {
exports.create_named_method("createArrayJson", create_array_json)?;
exports.create_named_method("createArray", create_array)?;
exports.create_named_method("createArrayWithSerdeTrait", create_array_with_serde_trait)?;
Ok(())
}
#[contextless_function]
pub fn create_array_json(env: Env) -> ContextlessResult<JsString> {
let a: Vec<u32> = vec![42; 1000];
let arr_string = to_string(&a)?;
env.create_string(arr_string.as_str()).map(Some)
}
#[contextless_function]
pub fn create_array(env: Env) -> ContextlessResult<JsObject> {
let a: Vec<u32> = vec![42; 1000];
let mut ret = env.create_array_with_length(a.len())?;
for (index, item) in a.iter().enumerate() {
ret.set_element(index as u32, env.create_uint32(*item)?)?;
}
Ok(Some(ret))
}
#[contextless_function]
pub fn create_array_with_serde_trait(env: Env) -> ContextlessResult<JsUnknown> {
let a: Vec<u32> = vec![42; 1000];
env.to_js_value(&a).map(Some)
}

View file

@ -0,0 +1,34 @@
use napi::{CallContext, JsObject, JsString, JsUndefined, JsUnknown, Result};
use serde_json::from_str;
pub fn register_js(exports: &mut JsObject) -> Result<()> {
exports.create_named_method("getArrayFromJson", get_array_from_json)?;
exports.create_named_method("getArrayFromJsArray", get_array_from_js_array)?;
exports.create_named_method("getArrayWithForLoop", get_array_with_for_loop)?;
Ok(())
}
#[js_function(1)]
fn get_array_from_json(ctx: CallContext) -> Result<JsUndefined> {
let input = ctx.get::<JsString>(0)?.into_utf8()?;
let _: Vec<u32> = from_str(input.as_str()?)?;
ctx.env.get_undefined()
}
#[js_function(1)]
fn get_array_from_js_array(ctx: CallContext) -> Result<JsUndefined> {
let input = ctx.get::<JsObject>(0)?;
let _: Vec<u32> = ctx.env.from_js_value(input)?;
ctx.env.get_undefined()
}
#[js_function(1)]
fn get_array_with_for_loop(ctx: CallContext) -> Result<JsUndefined> {
let input = ctx.get::<JsObject>(0)?;
let array_length = input.get_array_length_unchecked()? as usize;
let mut result: Vec<JsUnknown> = Vec::with_capacity(array_length);
for i in 0..array_length {
result.insert(i, input.get_element::<JsUnknown>(i as u32)?);
}
ctx.env.get_undefined()
}

View file

@ -13,7 +13,9 @@ static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
mod async_compute; mod async_compute;
mod buffer; mod buffer;
mod create_array;
mod get_set_property; mod get_set_property;
mod get_value_from_js;
mod noop; mod noop;
mod plus; mod plus;
@ -25,6 +27,8 @@ fn init(mut exports: JsObject, env: Env) -> Result<()> {
buffer::register_js(&mut exports)?; buffer::register_js(&mut exports)?;
plus::register_js(&mut exports)?; plus::register_js(&mut exports)?;
get_set_property::register_js(&mut exports, &env)?; get_set_property::register_js(&mut exports, &env)?;
create_array::register_js(&mut exports)?;
get_value_from_js::register_js(&mut exports)?;
Ok(()) Ok(())
} }

View file

@ -24,13 +24,8 @@ export class CreateNpmDirCommand extends Command {
) => { ) => {
const pkgJsonDir = config const pkgJsonDir = config
debug(`Read content from [${chalk.yellowBright(pkgJsonDir)}]`) debug(`Read content from [${chalk.yellowBright(pkgJsonDir)}]`)
const { const { platforms, packageName, version, binaryName, content } =
platforms, getNapiConfig(pkgJsonDir, cwd)
packageName,
version,
binaryName,
content,
} = getNapiConfig(pkgJsonDir, cwd)
for (const platformDetail of platforms) { for (const platformDetail of platforms) {
const targetDir = join( const targetDir = join(

View file

@ -39,13 +39,8 @@ export class PrePublishCommand extends Command {
@Command.Path('prepublish') @Command.Path('prepublish')
async execute() { async execute() {
const { const { packageJsonPath, platforms, version, packageName, binaryName } =
packageJsonPath, getNapiConfig(this.configFileName)
platforms,
version,
packageName,
binaryName,
} = getNapiConfig(this.configFileName)
debug(`Update optionalDependencies in [${packageJsonPath}]`) debug(`Update optionalDependencies in [${packageJsonPath}]`)
if (!this.isDryRun) { if (!this.isDryRun) {
await VersionCommand.updatePackageJson(this.prefix, this.configFileName) await VersionCommand.updatePackageJson(this.prefix, this.configFileName)

View file

@ -1292,7 +1292,7 @@ impl Env {
pub fn from_js_value<T, V>(&self, value: V) -> Result<T> pub fn from_js_value<T, V>(&self, value: V) -> Result<T>
where where
T: DeserializeOwned + ?Sized, T: DeserializeOwned + ?Sized,
V: NapiValue, V: NapiRaw,
{ {
let value = Value { let value = Value {
env: self.0, env: self.0,

View file

@ -90,7 +90,7 @@ impl JsFunction {
#[inline] #[inline]
pub fn new<V>(&self, args: &[V]) -> Result<JsObject> pub fn new<V>(&self, args: &[V]) -> Result<JsObject>
where where
V: NapiValue, V: NapiRaw,
{ {
let mut js_instance = ptr::null_mut(); let mut js_instance = ptr::null_mut();
let length = args.len(); let length = args.len();

View file

@ -2,7 +2,7 @@ use std::convert::From;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use crate::{check_status, sys, Callback, Env, NapiValue, Result}; use crate::{check_status, sys, Callback, Env, NapiRaw, Result};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Property<'env> { pub struct Property<'env> {
@ -56,7 +56,7 @@ impl<'env> Property<'env> {
} }
#[inline] #[inline]
pub fn with_value<T: NapiValue>(mut self, value: T) -> Self { pub fn with_value<T: NapiRaw>(mut self, value: T) -> Self {
self.raw_descriptor.value = unsafe { T::raw(&value) }; self.raw_descriptor.value = unsafe { T::raw(&value) };
self self
} }

View file

@ -18,12 +18,12 @@
"build:test:android": "yarn --cwd ./test_module build --target aarch64-linux-android", "build:test:android": "yarn --cwd ./test_module build --target aarch64-linux-android",
"build:test:armv7": "yarn --cwd ./test_module build-armv7", "build:test:armv7": "yarn --cwd ./test_module build-armv7",
"format": "run-p format:md format:json format:yaml format:source format:rs", "format": "run-p format:md format:json format:yaml format:source format:rs",
"format:md": "prettier --parser markdown --write './**/*.md'", "format:md": "prettier --parser markdown --write ./**/*.md",
"format:json": "prettier --parser json --write './**/*.json'", "format:json": "prettier --parser json --write ./**/*.json",
"format:rs": "cargo fmt", "format:rs": "cargo fmt",
"format:source": "prettier --config ./package.json --write './**/*.{js,ts}'", "format:source": "prettier --config ./package.json --write ./**/*.{js,ts}",
"format:yaml": "prettier --parser yaml --write './**/*.{yml,yaml}'", "format:yaml": "prettier --parser yaml --write ./**/*.{yml,yaml}",
"lint": "eslint -c .eslintrc.yml './cli/**/*.ts' './test_module/**/*.{ts,js}'", "lint": "eslint -c .eslintrc.yml ./cli/**/*.ts ./test_module/**/*.{ts,js}",
"prepublishOnly": "npm run build && pinst --disable", "prepublishOnly": "npm run build && pinst --disable",
"test": "ava", "test": "ava",
"postinstall": "husky install", "postinstall": "husky install",