From 1f45d5344c7049d8997a011b5378b73dce0f8d7a Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 24 Sep 2022 14:10:29 -0700 Subject: [PATCH 1/2] Use the browser's IdleDeadline to determine max task time --- src/common/Idle.ts | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/common/Idle.ts b/src/common/Idle.ts index 529d38a4..2aebc599 100644 --- a/src/common/Idle.ts +++ b/src/common/Idle.ts @@ -11,16 +11,8 @@ export class IdleTaskQueue { private _tasks: (() => void)[] = []; private _idleCallback?: number; - private _maxTaskDuration: number; private _i = 0; - /** - * @param targetFps The target frame rate. - */ - constructor(targetFps: number = 240) { - this._maxTaskDuration = 1000 / targetFps; - } - /** * Adds a task to the queue which will run in a future idle callback. */ @@ -53,16 +45,22 @@ export class IdleTaskQueue { private _start(): void { if (!this._idleCallback) { - this._idleCallback = requestIdleCallback(() => this._process()); + this._idleCallback = requestIdleCallback(this._process.bind(this)); } } - private _process(): void { - const start = performance.now(); + private _process(deadline: IdleDeadline): void { this._idleCallback = undefined; + let taskDuration = 0; + let longestTask = 0; while (this._i < this._tasks.length) { + taskDuration = performance.now(); this._tasks[this._i++](); - if (performance.now() - start > this._maxTaskDuration) { + taskDuration = performance.now() - taskDuration; + longestTask = Math.max(taskDuration, longestTask); + // Guess the following task will take a similar time to task that just finished, allow + // additional room to try avoid exceeding the deadline + if (longestTask * 1.5 > deadline.timeRemaining()) { this._start(); return; } @@ -71,14 +69,15 @@ export class IdleTaskQueue { } } +/** + * An object that tracks a single debounced task that will run on the next idle frame. When called + * multiple times, only the last set task will run. + */ export class DebouncedIdleTask { private _queue: IdleTaskQueue; - /** - * @param targetFps The target frame rate. - */ - constructor(targetFps: number = 240) { - this._queue = new IdleTaskQueue(targetFps); + constructor() { + this._queue = new IdleTaskQueue(); } public set(task: () => void): void { From ab90dcd0dc2562a6d0952eeca5c5d531bdb9851b Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 24 Sep 2022 14:13:04 -0700 Subject: [PATCH 2/2] Clarify comment --- src/common/Idle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Idle.ts b/src/common/Idle.ts index 2aebc599..e05ad068 100644 --- a/src/common/Idle.ts +++ b/src/common/Idle.ts @@ -58,7 +58,7 @@ export class IdleTaskQueue { this._tasks[this._i++](); taskDuration = performance.now() - taskDuration; longestTask = Math.max(taskDuration, longestTask); - // Guess the following task will take a similar time to task that just finished, allow + // Guess the following task will take a similar time to the longest task in this batch, allow // additional room to try avoid exceeding the deadline if (longestTask * 1.5 > deadline.timeRemaining()) { this._start();