mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
perf(core): minimize trivial heap allocations in resolve_async_ops
(#16584)
* Use stack allocated array for 16 promises and spill rest to heap. the exact number can change, maybe 128? (tokio's coop budget limit) * Avoid v8::Global::clone for global context. * Do not open global opresolve when its not needed.
This commit is contained in:
parent
bc33a4b2e0
commit
110a0ebe69
3 changed files with 15 additions and 5 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -943,6 +943,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"serde_v8",
|
||||
"smallvec",
|
||||
"sourcemap",
|
||||
"tokio",
|
||||
"url",
|
||||
|
|
|
@ -32,6 +32,7 @@ pin-project = "1.0.11"
|
|||
serde = { version = "1.0.136", features = ["derive"] }
|
||||
serde_json = { version = "1.0.79", features = ["preserve_order"] }
|
||||
serde_v8 = { version = "0.69.0", path = "../serde_v8" }
|
||||
smallvec = "1.8"
|
||||
sourcemap = "6.1"
|
||||
url = { version = "2.3.1", features = ["serde", "expose_internals"] }
|
||||
v8 = { version = "0.54.0", default-features = false }
|
||||
|
|
|
@ -32,6 +32,7 @@ use futures::future::FutureExt;
|
|||
use futures::stream::FuturesUnordered;
|
||||
use futures::stream::StreamExt;
|
||||
use futures::task::AtomicWaker;
|
||||
use smallvec::SmallVec;
|
||||
use std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
@ -1972,10 +1973,13 @@ impl JsRuntime {
|
|||
// Send finished responses to JS
|
||||
fn resolve_async_ops(&mut self, cx: &mut Context) -> Result<(), Error> {
|
||||
let isolate = self.v8_isolate.as_mut().unwrap();
|
||||
|
||||
let js_recv_cb_handle = self.state.borrow().js_recv_cb.clone().unwrap();
|
||||
let global_realm = self.state.borrow().global_realm.clone().unwrap();
|
||||
let scope = &mut global_realm.handle_scope(isolate);
|
||||
let scope = &mut self
|
||||
.state
|
||||
.borrow()
|
||||
.global_realm
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.handle_scope(isolate);
|
||||
|
||||
// We return async responses to JS in unbounded batches (may change),
|
||||
// each batch is a flat vector of tuples:
|
||||
|
@ -1984,7 +1988,10 @@ impl JsRuntime {
|
|||
// which contains a value OR an error, encoded as a tuple.
|
||||
// This batch is received in JS via the special `arguments` variable
|
||||
// and then each tuple is used to resolve or reject promises
|
||||
let mut args: Vec<v8::Local<v8::Value>> = vec![];
|
||||
//
|
||||
// This can handle 16 promises (32 / 2) futures in a single batch without heap
|
||||
// allocations.
|
||||
let mut args: SmallVec<[v8::Local<v8::Value>; 32]> = SmallVec::new();
|
||||
|
||||
// Now handle actual ops.
|
||||
{
|
||||
|
@ -2010,6 +2017,7 @@ impl JsRuntime {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let js_recv_cb_handle = self.state.borrow().js_recv_cb.clone().unwrap();
|
||||
let tc_scope = &mut v8::TryCatch::new(scope);
|
||||
let js_recv_cb = js_recv_cb_handle.open(tc_scope);
|
||||
let this = v8::undefined(tc_scope).into();
|
||||
|
|
Loading…
Reference in a new issue