diff --git a/core/core.js b/core/core.js index 40a8270e3d..3ec5c3e41c 100644 --- a/core/core.js +++ b/core/core.js @@ -9,12 +9,53 @@ let opsCache = {}; const errorMap = {}; let nextPromiseId = 1; - const promiseTable = new Map(); + const promiseMap = new Map(); + const RING_SIZE = 4 * 1024; + const NO_PROMISE = null; // Alias to null is faster than plain nulls + const promiseRing = new Array(RING_SIZE).fill(NO_PROMISE); function init() { recv(handleAsyncMsgFromRust); } + function setPromise(promiseId) { + const idx = promiseId % RING_SIZE; + // Move old promise from ring to map + const oldPromise = promiseRing[idx]; + if (oldPromise !== NO_PROMISE) { + const oldPromiseId = promiseId - RING_SIZE; + promiseMap.set(oldPromiseId, oldPromise); + } + // Set new promise + return promiseRing[idx] = newPromise(); + } + + function getPromise(promiseId) { + // Check if out of ring bounds, fallback to map + const outOfBounds = promiseId < nextPromiseId - RING_SIZE; + if (outOfBounds) { + const promise = promiseMap.get(promiseId); + promiseMap.delete(promiseId); + return promise; + } + // Otherwise take from ring + const idx = promiseId % RING_SIZE; + const promise = promiseRing[idx]; + promiseRing[idx] = NO_PROMISE; + return promise; + } + + function newPromise() { + let resolve, reject; + const promise = new Promise((resolve_, reject_) => { + resolve = resolve_; + reject = reject_; + }); + promise.resolve = resolve; + promise.reject = reject; + return promise; + } + function ops() { // op id 0 is a special value to retrieve the map of registered ops. const newOpsCache = Object.fromEntries(send(0)); @@ -71,15 +112,7 @@ const maybeError = dispatch(opName, promiseId, args, zeroCopy); // Handle sync error (e.g: error parsing args) if (maybeError) processResponse(maybeError); - let resolve, reject; - const promise = new Promise((resolve_, reject_) => { - resolve = resolve_; - reject = reject_; - }); - promise.resolve = resolve; - promise.reject = reject; - promiseTable.set(promiseId, promise); - return promise; + return setPromise(promiseId); } function jsonOpSync(opName, args = null, zeroCopy = null) { @@ -87,8 +120,7 @@ } function opAsyncHandler(promiseId, res) { - const promise = promiseTable.get(promiseId); - promiseTable.delete(promiseId); + const promise = getPromise(promiseId); if (!isErr(res)) { promise.resolve(res); } else {