mirror of
https://github.com/denoland/deno.git
synced 2025-09-29 05:34:49 +00:00
refactor(core): limit number of boundary crossings between Rust and V8 (#18652)
This commit refactors "deno_core" to do fewer boundary crossings from Rust to V8. In other words we are now calling V8 from Rust fewer times. This is done by merging 3 distinct callbacks into a single one. Instead of having "op resolve" callback, "next tick" callback and "macrotask queue" callback, we now have only "Deno.core.eventLoopTick" callback, which is responsible for doing the same actions previous 3 callbacks. On each of the event loop we were doing at least 2 boundary crosses (timers macrotask queue callback and unhandled promise rejection callback) and up to 4 crosses if there were op response and next tick callbacks coming from Node.js compatibility layer. Now this is all done in a single callback. Closes https://github.com/denoland/deno/issues/18620
This commit is contained in:
parent
d192d84a0e
commit
cb2ca234bb
18 changed files with 126 additions and 173 deletions
|
@ -133,13 +133,48 @@
|
|||
return promiseRing[idx] != NO_PROMISE;
|
||||
}
|
||||
|
||||
function opresolve() {
|
||||
for (let i = 0; i < arguments.length; i += 2) {
|
||||
const macrotaskCallbacks = [];
|
||||
const nextTickCallbacks = [];
|
||||
|
||||
function setMacrotaskCallback(cb) {
|
||||
ArrayPrototypePush(macrotaskCallbacks, cb);
|
||||
}
|
||||
|
||||
function setNextTickCallback(cb) {
|
||||
ArrayPrototypePush(nextTickCallbacks, cb);
|
||||
}
|
||||
|
||||
// This function has variable number of arguments. The last argument describes
|
||||
// if there's a "next tick" scheduled by the Node.js compat layer. Arguments
|
||||
// before last are alternating integers and any values that describe the
|
||||
// responses of async ops.
|
||||
function eventLoopTick() {
|
||||
// First respond to all pending ops.
|
||||
for (let i = 0; i < arguments.length - 1; i += 2) {
|
||||
const promiseId = arguments[i];
|
||||
const res = arguments[i + 1];
|
||||
const promise = getPromise(promiseId);
|
||||
promise.resolve(res);
|
||||
}
|
||||
// Drain nextTick queue if there's a tick scheduled.
|
||||
if (arguments[arguments.length - 1]) {
|
||||
for (let i = 0; i < nextTickCallbacks.length; i++) {
|
||||
nextTickCallbacks[i]();
|
||||
}
|
||||
} else {
|
||||
ops.op_run_microtasks();
|
||||
}
|
||||
// Finally drain macrotask queue.
|
||||
for (let i = 0; i < macrotaskCallbacks.length; i++) {
|
||||
const cb = macrotaskCallbacks[i];
|
||||
while (true) {
|
||||
const res = cb();
|
||||
ops.op_run_microtasks();
|
||||
if (res === true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function registerErrorClass(className, errorClass) {
|
||||
|
@ -406,7 +441,7 @@
|
|||
registerErrorBuilder,
|
||||
registerErrorClass,
|
||||
buildCustomError,
|
||||
opresolve,
|
||||
eventLoopTick,
|
||||
BadResource,
|
||||
BadResourcePrototype,
|
||||
Interrupted,
|
||||
|
@ -428,8 +463,8 @@
|
|||
writeSync: (rid, buffer) => ops.op_write_sync(rid, buffer),
|
||||
shutdown: opAsync.bind(null, "op_shutdown"),
|
||||
print: (msg, isErr) => ops.op_print(msg, isErr),
|
||||
setMacrotaskCallback: (fn) => ops.op_set_macrotask_callback(fn),
|
||||
setNextTickCallback: (fn) => ops.op_set_next_tick_callback(fn),
|
||||
setMacrotaskCallback,
|
||||
setNextTickCallback,
|
||||
runMicrotasks: () => ops.op_run_microtasks(),
|
||||
hasTickScheduled: () => ops.op_has_tick_scheduled(),
|
||||
setHasTickScheduled: (bool) => ops.op_set_has_tick_scheduled(bool),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue