test(napi): add memory tests for Reference
This commit is contained in:
parent
6a252c70d2
commit
63a557f6cc
10 changed files with 110 additions and 27 deletions
|
@ -30,6 +30,8 @@ pub unsafe extern "C" fn raw_finalize_unchecked<T>(
|
|||
REFERENCE_MAP.with(|reference_map| reference_map.borrow_mut().remove(&finalize_data))
|
||||
{
|
||||
let finalize_callbacks_rc = unsafe { Rc::from_raw(finalize_callbacks_ptr) };
|
||||
debug_assert!(Rc::strong_count(&finalize_callbacks_rc) == 1);
|
||||
debug_assert!(Rc::weak_count(&finalize_callbacks_rc) == 0);
|
||||
let finalize = unsafe { Box::from_raw(finalize_callbacks_rc.get()) };
|
||||
finalize();
|
||||
let delete_reference_status = unsafe { sys::napi_delete_reference(env, ref_val) };
|
||||
|
|
|
@ -16,7 +16,9 @@ napi = { path = "../crates/napi", features = [
|
|||
"latin1",
|
||||
"compat-mode",
|
||||
] }
|
||||
napi-derive = { path = "../crates/macro", features = ["compat-mode"] }
|
||||
napi-derive = { path = "../crates/macro", default-features = false, features = [
|
||||
"compat-mode",
|
||||
] }
|
||||
serde = "1"
|
||||
serde_bytes = "0.11"
|
||||
serde_derive = "1"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { createSuite } from './test-util.mjs'
|
||||
|
||||
await createSuite('reference')
|
||||
await createSuite('tokio-future')
|
||||
await createSuite('serde')
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "node ../cli/scripts/index.js build --release"
|
||||
"build": "node ../cli/scripts/index.js build --release --js false"
|
||||
},
|
||||
"dependencies": {
|
||||
"colorette": "^2.0.16",
|
||||
|
|
32
memory-testing/reference.mjs
Normal file
32
memory-testing/reference.mjs
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { createRequire } from 'module'
|
||||
|
||||
import { displayMemoryUsageFromNode } from './util.mjs'
|
||||
|
||||
const initialMemoryUsage = process.memoryUsage()
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
const { MemoryHolder } = require(`./index.node`)
|
||||
|
||||
const sleep = () =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve()
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
let i = 1
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const holder = new MemoryHolder(1024 * 1024)
|
||||
for (const _ of Array.from({ length: 100 })) {
|
||||
const child = holder.createReference()
|
||||
child.count()
|
||||
}
|
||||
if (i % 100 === 0) {
|
||||
displayMemoryUsageFromNode(initialMemoryUsage)
|
||||
await sleep()
|
||||
global.gc()
|
||||
}
|
||||
i++
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
const displayMemoryUsageFromNode = require('./util')
|
||||
import { createRequire } from 'module'
|
||||
|
||||
import { displayMemoryUsageFromNode } from './util.mjs'
|
||||
|
||||
const initialMemoryUsage = process.memoryUsage()
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
const api = require(`./index.node`)
|
||||
|
||||
const data = {
|
||||
|
@ -27,7 +31,7 @@ const data = {
|
|||
let i = 1
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
api.convertFromJS(data)
|
||||
api.fromJs(data)
|
||||
if (i % 100000 === 0) {
|
||||
displayMemoryUsageFromNode(initialMemoryUsage)
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
use napi::{bindgen_prelude::*, Env};
|
||||
|
||||
#[macro_use]
|
||||
extern crate napi_derive;
|
||||
#[macro_use]
|
||||
|
@ -34,8 +36,8 @@ pub struct Room {
|
|||
name: String,
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
fn test_async(ctx: napi::CallContext) -> napi::Result<napi::JsObject> {
|
||||
#[napi]
|
||||
pub fn test_async(env: Env) -> napi::Result<napi::JsObject> {
|
||||
let data = serde_json::json!({
|
||||
"findFirstBooking": {
|
||||
"id": "ckovh15xa104945sj64rdk8oas",
|
||||
|
@ -57,26 +59,62 @@ fn test_async(ctx: napi::CallContext) -> napi::Result<napi::JsObject> {
|
|||
"room": { "id": "ckovh15xa104955sj6r2tqaw1c", "name": "38683b87f2664" }
|
||||
}
|
||||
});
|
||||
|
||||
ctx.env.execute_tokio_future(
|
||||
env.execute_tokio_future(
|
||||
async move { Ok(serde_json::to_string(&data).unwrap()) },
|
||||
|env, response| {
|
||||
env.adjust_external_memory(response.len() as i64)?;
|
||||
env.create_string_from_std(response)
|
||||
|env, res| {
|
||||
env.adjust_external_memory(res.len() as i64)?;
|
||||
env.create_string_from_std(res)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
fn from_js(ctx: napi::CallContext) -> napi::Result<napi::JsString> {
|
||||
let input_object = ctx.get::<napi::JsObject>(0)?;
|
||||
let a: Welcome = ctx.env.from_js_value(&input_object)?;
|
||||
ctx.env.create_string_from_std(serde_json::to_string(&a)?)
|
||||
#[napi]
|
||||
pub fn from_js(env: Env, input_object: Object) -> napi::Result<String> {
|
||||
let a: Welcome = env.from_js_value(&input_object)?;
|
||||
Ok(serde_json::to_string(&a)?)
|
||||
}
|
||||
|
||||
#[module_exports]
|
||||
fn init(mut exports: napi::JsObject) -> napi::Result<()> {
|
||||
exports.create_named_method("testAsync", test_async)?;
|
||||
exports.create_named_method("convertFromJS", from_js)?;
|
||||
Ok(())
|
||||
pub struct ChildHolder {
|
||||
inner: &'static MemoryHolder,
|
||||
}
|
||||
|
||||
impl ChildHolder {
|
||||
fn count(&self) -> usize {
|
||||
self.inner.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub struct MemoryHolder(Vec<u8>);
|
||||
|
||||
#[napi]
|
||||
impl MemoryHolder {
|
||||
#[napi(constructor)]
|
||||
pub fn new(mut env: Env, len: u32) -> Result<Self> {
|
||||
env.adjust_external_memory(len as i64)?;
|
||||
Ok(Self(vec![42; len as usize]))
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn create_reference(
|
||||
&self,
|
||||
env: Env,
|
||||
holder_ref: Reference<MemoryHolder>,
|
||||
) -> Result<ChildReference> {
|
||||
let child_holder =
|
||||
holder_ref.share_with(env, |holder_ref| Ok(ChildHolder { inner: holder_ref }))?;
|
||||
Ok(ChildReference(child_holder))
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub struct ChildReference(SharedReference<MemoryHolder, ChildHolder>);
|
||||
|
||||
#[napi]
|
||||
|
||||
impl ChildReference {
|
||||
#[napi]
|
||||
pub fn count(&self) -> u32 {
|
||||
self.0.count() as u32
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export async function createSuite(testFile, maxMemoryUsage) {
|
|||
|
||||
const container = await client.createContainer({
|
||||
Image: 'node:lts-slim',
|
||||
Cmd: ['/bin/bash', '-c', `node memory-testing/${testFile}.js`],
|
||||
Cmd: ['/bin/bash', '-c', `node --expose-gc memory-testing/${testFile}.mjs`],
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Tty: true,
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
const displayMemoryUsageFromNode = require('./util')
|
||||
import { createRequire } from 'module'
|
||||
|
||||
import { displayMemoryUsageFromNode } from './util.mjs'
|
||||
|
||||
const initialMemoryUsage = process.memoryUsage()
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
const api = require(`./index.node`)
|
||||
|
||||
async function main() {
|
|
@ -1,8 +1,8 @@
|
|||
const { whiteBright, red, green, gray } = require('colorette')
|
||||
const prettyBytes = require('pretty-bytes')
|
||||
const { table } = require('table')
|
||||
import { whiteBright, red, green, gray } from 'colorette'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import { table } from 'table'
|
||||
|
||||
module.exports = function displayMemoryUsageFromNode(initialMemoryUsage) {
|
||||
export function displayMemoryUsageFromNode(initialMemoryUsage) {
|
||||
const finalMemoryUsage = process.memoryUsage()
|
||||
const titles = Object.keys(initialMemoryUsage).map((k) => whiteBright(k))
|
||||
const tableData = [titles]
|
Loading…
Reference in a new issue