summaryrefslogtreecommitdiff
path: root/ext/web/02_timers.js
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-06-14 17:04:49 +0200
committerGitHub <noreply@github.com>2023-06-14 17:04:49 +0200
commit348287825cdefecdd6dda6ce5c8652fdfc69837c (patch)
tree223e124cc9b3a27fc879dbf5f487249a208f9804 /ext/web/02_timers.js
parent5ef225853c0f81ba0a7d1ce888ab3b2d283eae0a (diff)
perf(web): optimize timer resolution (#19493)
Closes https://github.com/denoland/deno/issues/19348 This changes benchmark from the issue from: ``` deno run -A https://raw.githubusercontent.com/nats-io/nats.deno/deno-transport-changes/examples/bench.js --subject a --payload 3500 --pub --count 650000 pub 7,636 msgs/sec - [85.13 secs] ~ 25.49 MB/sec 85127.8765/85127.8765 ``` to: ``` > ./target/release/deno run -A https://raw.githubusercontent.com/nats-io/nats.deno/deno-transport-changes/examples/bench.js --subject a --payload 3500 --pub --count 650000 pub 176,840 msgs/sec - [3.68 secs] ~ 590.27 MB/sec 3675.646833/3675.646833 > ./target/release/deno run -A https://raw.githubusercontent.com/nats-io/nats.deno/deno-transport-changes/examples/bench.js --subject a --payload 3500 --pub --count 650000 pub 174,589 msgs/sec - [3.72 secs] ~ 582.76 MB/sec 3723.01925/3723.01925 ```
Diffstat (limited to 'ext/web/02_timers.js')
-rw-r--r--ext/web/02_timers.js33
1 files changed, 16 insertions, 17 deletions
diff --git a/ext/web/02_timers.js b/ext/web/02_timers.js
index 27e2e953d..cfabdeb98 100644
--- a/ext/web/02_timers.js
+++ b/ext/web/02_timers.js
@@ -15,7 +15,6 @@ const {
MapPrototypeSet,
Uint8Array,
Uint32Array,
- NumberPOSITIVE_INFINITY,
PromisePrototypeThen,
SafeArrayIterator,
SafeMap,
@@ -190,7 +189,7 @@ function initializeTimer(
// 13. Run steps after a timeout given global, "setTimeout/setInterval",
// timeout, completionStep, and id.
runAfterTimeout(
- () => ArrayPrototypePush(timerTasks, task),
+ task,
timeout,
timerInfo,
);
@@ -203,7 +202,7 @@ function initializeTimer(
/**
* @typedef ScheduledTimer
* @property {number} millis
- * @property {() => void} cb
+ * @property { {action: () => void, nestingLevel: number}[] } task
* @property {boolean} resolved
* @property {ScheduledTimer | null} prev
* @property {ScheduledTimer | null} next
@@ -216,12 +215,12 @@ function initializeTimer(
const scheduledTimers = { head: null, tail: null };
/**
- * @param {() => void} cb Will be run after the timeout, if it hasn't been
- * cancelled.
+ * @param { {action: () => void, nestingLevel: number}[] } task Will be run
+ * after the timeout, if it hasn't been cancelled.
* @param {number} millis
* @param {{ cancelRid: number, isRef: boolean, promiseId: number }} timerInfo
*/
-function runAfterTimeout(cb, millis, timerInfo) {
+function runAfterTimeout(task, millis, timerInfo) {
const cancelRid = timerInfo.cancelRid;
let sleepPromise;
// If this timeout is scheduled for 0ms it means we want it to run at the
@@ -241,7 +240,6 @@ function runAfterTimeout(cb, millis, timerInfo) {
/** @type {ScheduledTimer} */
const timerObject = {
millis,
- cb,
resolved: false,
prev: scheduledTimers.tail,
next: null,
@@ -260,6 +258,10 @@ function runAfterTimeout(cb, millis, timerInfo) {
PromisePrototypeThen(
sleepPromise,
(cancelled) => {
+ if (timerObject.resolved) {
+ return;
+ }
+
// "op_void_async_deferred" returns null
if (cancelled !== null && !cancelled) {
// The timer was cancelled.
@@ -280,18 +282,15 @@ function runAfterTimeout(cb, millis, timerInfo) {
// b) its timeout is lower than the lowest unresolved timeout found so
// far in the list.
- timerObject.resolved = true;
-
- let lowestUnresolvedTimeout = NumberPOSITIVE_INFINITY;
-
let currentEntry = scheduledTimers.head;
while (currentEntry !== null) {
- if (currentEntry.millis < lowestUnresolvedTimeout) {
- if (currentEntry.resolved) {
- currentEntry.cb();
- removeFromScheduledTimers(currentEntry);
- } else {
- lowestUnresolvedTimeout = currentEntry.millis;
+ if (currentEntry.millis <= timerObject.millis) {
+ currentEntry.resolved = true;
+ ArrayPrototypePush(timerTasks, task);
+ removeFromScheduledTimers(currentEntry);
+
+ if (currentEntry === timerObject) {
+ break;
}
}