perf: remove knowledge of promise IDs from deno (#21132)

We can move all promise ID knowledge to deno_core, allowing us to better
experiment with promise implementation in deno_core.

`{un,}refOpPromise(promise)` is equivalent to
`{un,}refOp(promise[promiseIdSymbol])`
This commit is contained in:
Matt Mastracci 2023-11-09 13:57:26 -07:00 committed by GitHub
parent c4029f6af2
commit 9010b8df53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 70 additions and 124 deletions

View file

@ -13,23 +13,21 @@ import { SymbolDispose } from "ext:deno_web/00_infra.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeFilter,
ArrayPrototypeForEach,
ArrayPrototypePush,
Error,
Number,
ObjectPrototypeIsPrototypeOf,
PromiseResolve,
SafeSet,
SetPrototypeAdd,
SetPrototypeDelete,
SetPrototypeForEach,
SymbolAsyncIterator,
Symbol,
SymbolFor,
TypeError,
TypedArrayPrototypeSubarray,
Uint8Array,
} = primordials;
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
async function write(rid, data) {
return await core.write(rid, data);
}
@ -70,7 +68,7 @@ class Conn {
#remoteAddr = null;
#localAddr = null;
#unref = false;
#pendingReadPromiseIds = [];
#pendingReadPromises = new SafeSet();
#readable;
#writable;
@ -102,19 +100,15 @@ class Conn {
return 0;
}
const promise = core.read(this.rid, buffer);
const promiseId = promise[promiseIdSymbol];
if (this.#unref) core.unrefOp(promiseId);
ArrayPrototypePush(this.#pendingReadPromiseIds, promiseId);
if (this.#unref) core.unrefOpPromise(promise);
SetPrototypeAdd(this.#pendingReadPromises, promise);
let nread;
try {
nread = await promise;
} catch (e) {
throw e;
} finally {
this.#pendingReadPromiseIds = ArrayPrototypeFilter(
this.#pendingReadPromiseIds,
(id) => id !== promiseId,
);
SetPrototypeDelete(this.#pendingReadPromises, promise);
}
return nread === 0 ? null : nread;
}
@ -149,7 +143,11 @@ class Conn {
if (this.#readable) {
readableStreamForRidUnrefableRef(this.#readable);
}
ArrayPrototypeForEach(this.#pendingReadPromiseIds, (id) => core.refOp(id));
SetPrototypeForEach(
this.#pendingReadPromises,
(promise) => core.refOpPromise(promise),
);
}
unref() {
@ -157,9 +155,9 @@ class Conn {
if (this.#readable) {
readableStreamForRidUnrefableUnref(this.#readable);
}
ArrayPrototypeForEach(
this.#pendingReadPromiseIds,
(id) => core.unrefOp(id),
SetPrototypeForEach(
this.#pendingReadPromises,
(promise) => core.unrefOpPromise(promise),
);
}
@ -184,7 +182,7 @@ class Listener {
#rid = 0;
#addr = null;
#unref = false;
#promiseId = null;
#promise = null;
constructor(rid, addr) {
this.#rid = rid;
@ -211,10 +209,10 @@ class Listener {
default:
throw new Error(`Unsupported transport: ${this.addr.transport}`);
}
this.#promiseId = promise[promiseIdSymbol];
if (this.#unref) core.unrefOp(this.#promiseId);
this.#promise = promise;
if (this.#unref) core.unrefOpPromise(promise);
const { 0: rid, 1: localAddr, 2: remoteAddr } = await promise;
this.#promiseId = null;
this.#promise = null;
if (this.addr.transport == "tcp") {
localAddr.transport = "tcp";
remoteAddr.transport = "tcp";
@ -265,15 +263,15 @@ class Listener {
ref() {
this.#unref = false;
if (typeof this.#promiseId === "number") {
core.refOp(this.#promiseId);
if (this.#promise !== null) {
core.refOpPromise(this.#promise);
}
}
unref() {
this.#unref = true;
if (typeof this.#promiseId === "number") {
core.unrefOp(this.#promiseId);
if (this.#promise !== null) {
core.unrefOpPromise(this.#promise);
}
}
}