erksch
erksch
DDeno
Created by erksch on 9/23/2024 in #help
RustyV8: Example of using PromiseResolver / async?
Is there an example using PromiseResolver? Because it uses a HandleScope, I'm unsure about how to reference it at a later point when async work has been done. Could you provide an example of implementing a async simple sleep function, ideally by pushing an async task to the main Tokio runtime? Problem:
borrowed data escapes outside of closure
`scope` escapes the closure body here
borrowed data escapes outside of closure
`scope` escapes the closure body here
From JS: await doRustAsync(5000); Calling RS:
let export_do_rust_async = |scope: &mut v8::HandleScope,
_args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue| {
let millis = args.get(0).to_number(scope).unwrap().value() as u64;

let resolver = v8::PromiseResolver::new(scope).unwrap();
let promise = resolver.get_promise(scope);
rv.set(promise.into());

tokio::spawn(async move {
// Do async work
tokio::time::sleep(Duration::from_millis(millis)).await;
promise.resolve()
});
};
let export_do_rust_async = |scope: &mut v8::HandleScope,
_args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue| {
let millis = args.get(0).to_number(scope).unwrap().value() as u64;

let resolver = v8::PromiseResolver::new(scope).unwrap();
let promise = resolver.get_promise(scope);
rv.set(promise.into());

tokio::spawn(async move {
// Do async work
tokio::time::sleep(Duration::from_millis(millis)).await;
promise.resolve()
});
};
This Rust code obviously doesn't work, since: 1. the tokio runtime handle isn't available to the thread. 2. the promise/resolver uses scope, which is borrowed.
16 replies
DDeno
Created by erksch on 9/22/2024 in #help
Embedding RustyV8: Fatal JavaScript out of memory: Reached heap limit
I created this Criterion benchmark to estimate the cost of serialization, but it runs out of memory. Am I supposed to destroy json_v8_str and _json_obj explicitly?
let platform = v8::new_default_platform(0, false).make_shared();
v8::V8::initialize_platform(platform);
v8::V8::initialize();

let isolate = &mut v8::Isolate::new(Default::default());
let isolate_scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(isolate_scope, Default::default());
let scope = &mut v8::ContextScope::new(isolate_scope, context);
let global = context.global(scope);

// JSON
let json_str = r#"{"key": "value", "number": 42}"#;
let json_v8_str = v8::String::new(scope, json_str).unwrap();
let json_obj = v8::json::parse(scope, json_v8_str).unwrap();

let key = v8::String::new(scope, "key").unwrap();
let new_value = v8::String::new(scope, "newValue").unwrap();
let obj = json_obj.to_object(scope).unwrap();
obj.set(scope, key.into(), new_value.into());

let modified_json = v8::json::stringify(scope, obj.into()).unwrap();
let rust_str = modified_json.to_rust_string_lossy(scope);
assert_eq!(rust_str, r#"{"key":"newValue","number":42}"#);

c.bench_function("v8 json deserialize", |b| {
b.iter(|| {
let json_str = r#"{"key": "value", "number": 42}"#;
let json_v8_str = v8::String::new(scope, json_str).unwrap();
let _json_obj = v8::json::parse(scope, json_v8_str).unwrap();
})
});
let platform = v8::new_default_platform(0, false).make_shared();
v8::V8::initialize_platform(platform);
v8::V8::initialize();

let isolate = &mut v8::Isolate::new(Default::default());
let isolate_scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(isolate_scope, Default::default());
let scope = &mut v8::ContextScope::new(isolate_scope, context);
let global = context.global(scope);

// JSON
let json_str = r#"{"key": "value", "number": 42}"#;
let json_v8_str = v8::String::new(scope, json_str).unwrap();
let json_obj = v8::json::parse(scope, json_v8_str).unwrap();

let key = v8::String::new(scope, "key").unwrap();
let new_value = v8::String::new(scope, "newValue").unwrap();
let obj = json_obj.to_object(scope).unwrap();
obj.set(scope, key.into(), new_value.into());

let modified_json = v8::json::stringify(scope, obj.into()).unwrap();
let rust_str = modified_json.to_rust_string_lossy(scope);
assert_eq!(rust_str, r#"{"key":"newValue","number":42}"#);

c.bench_function("v8 json deserialize", |b| {
b.iter(|| {
let json_str = r#"{"key": "value", "number": 42}"#;
let json_v8_str = v8::String::new(scope, json_str).unwrap();
let _json_obj = v8::json::parse(scope, json_v8_str).unwrap();
})
});
<--- Last few GCs --->

[417610:0xc03ef79a0000] 14221 ms: Mark-Compact (reduce) 1399.0 (1399.9) -> 1399.0 (1400.9) MB, pooled: 0 MB, 562.58 / 0.00 ms (+ 0.0 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 739 ms) (average mu = 0.809[417610:0xc03ef79a0000] 15192 ms: Mark-Compact 1400.0 (1400.9) -> 1400.0 (1404.9) MB, pooled: 0 MB, 969.39 / 0.00 ms (average mu = 0.600, current mu = 0.002) allocation failure; scavenge might not succeed


<--- JS stacktrace --->



#
# Fatal JavaScript out of memory: Reached heap limit
<--- Last few GCs --->

[417610:0xc03ef79a0000] 14221 ms: Mark-Compact (reduce) 1399.0 (1399.9) -> 1399.0 (1400.9) MB, pooled: 0 MB, 562.58 / 0.00 ms (+ 0.0 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 739 ms) (average mu = 0.809[417610:0xc03ef79a0000] 15192 ms: Mark-Compact 1400.0 (1400.9) -> 1400.0 (1404.9) MB, pooled: 0 MB, 969.39 / 0.00 ms (average mu = 0.600, current mu = 0.002) allocation failure; scavenge might not succeed


<--- JS stacktrace --->



#
# Fatal JavaScript out of memory: Reached heap limit
4 replies