From 4759a8c2beff62ff60368d05f125f067030cf3de Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Thu, 8 Sep 2022 18:34:42 -0500 Subject: [PATCH] fix(animationFrameScheduler): improve performance of animationFrameScheduler + Changes the check for existing action ids to simply check the last action in the queue to see if its id matches. Previously we were doing an O(n) loop on each execution of an action to check to see if the scheduling id needed to be recycled. This is problematic in AsapScheduler and AnimationFrameScheduler, where we're not reusing an interval. Since AsapScheduler and AnimationFrameScheduler reuse the most recent action id until their scheduled microtask or animation frame fires, the last action in the actions queue array is all we really need to check (rather than checking them all with `some`). O(1) vs O(n). + Refactors a weird conditional gaff from `if ((X && A) || (!X && B))` to just be `if (X ? A : B)` resolves #7017 related #7018 related #6674 --- src/internal/scheduler/AnimationFrameAction.ts | 5 +++-- src/internal/scheduler/AsapAction.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/internal/scheduler/AnimationFrameAction.ts b/src/internal/scheduler/AnimationFrameAction.ts index f9b07be8ed..f9c8f8e39d 100644 --- a/src/internal/scheduler/AnimationFrameAction.ts +++ b/src/internal/scheduler/AnimationFrameAction.ts @@ -26,13 +26,14 @@ export class AnimationFrameAction extends AsyncAction { // If delay exists and is greater than 0, or if the delay is null (the // action wasn't rescheduled) but was originally scheduled as an async // action, then recycle as an async action. - if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) { + if (delay != null ? delay > 0 : this.delay > 0) { return super.recycleAsyncId(scheduler, id, delay); } // If the scheduler queue has no remaining actions with the same async id, // cancel the requested animation frame and set the scheduled flag to // undefined so the next AnimationFrameAction will request its own. - if (id != null && !scheduler.actions.some((action) => action.id === id)) { + const { actions } = scheduler; + if (id != null && actions[actions.length - 1]?.id !== id) { animationFrameProvider.cancelAnimationFrame(id as number); scheduler._scheduled = undefined; } diff --git a/src/internal/scheduler/AsapAction.ts b/src/internal/scheduler/AsapAction.ts index 503d306b2c..bd4b8697c3 100644 --- a/src/internal/scheduler/AsapAction.ts +++ b/src/internal/scheduler/AsapAction.ts @@ -26,13 +26,14 @@ export class AsapAction extends AsyncAction { // If delay exists and is greater than 0, or if the delay is null (the // action wasn't rescheduled) but was originally scheduled as an async // action, then recycle as an async action. - if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) { + if (delay != null ? delay > 0 : this.delay > 0) { return super.recycleAsyncId(scheduler, id, delay); } // If the scheduler queue has no remaining actions with the same async id, // cancel the requested microtask and set the scheduled flag to undefined // so the next AsapAction will request its own. - if (id != null && !scheduler.actions.some((action) => action.id === id)) { + const { actions } = scheduler; + if (id != null && actions[actions.length - 1]?.id !== id) { immediateProvider.clearImmediate(id); scheduler._scheduled = undefined; }