fix(utils): ensure consistent throttle to next frame#6409
Merged
steveruizok merged 7 commits intomainfrom Jul 10, 2025
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
mimecuvalo
reviewed
Jul 8, 2025
Member
mimecuvalo
left a comment
There was a problem hiding this comment.
this feels like a time where we shouldn't be maintaining/rebuilding this in-house.
why aren't we just using lodash → throttle?
Collaborator
Author
Its not really a throttle function, its about our tick / maximum FPS |
steveruizok
commented
Jul 10, 2025
| let frame: number | undefined | ||
| let time = 0 | ||
| let last = 0 | ||
| const targetTimePerFrame = Math.floor(1000 / targetFps) // 16ms |
Collaborator
Author
There was a problem hiding this comment.
I think this is better
Collaborator
Author
|
bless me i'm landing |
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request refactors the
throttleutility inpackages/utils/src/lib/throttle.ts, used inthrottleToNextFrame.Fixes a case where the timeout could fire too often (or irregularly) due to the saving up of overflow ms.
Fixes a case where the timeout could fire too late due to a second raf.
How it works
Overflow
Previously, when
tickrecognized that 16ms or more of time had elapsed since the previous tick, it would stash any additional ms for next time. So for example a frame with a 18ms would cause the tick to run, with the "extra" 2ms stashed for next time, so that a following frame at 14ms would cause the tick to run again. This is intended to make the tick more regular, however it can also produce ticks that, being too close together, seemed to lead to make long frames harder to recover from. I think it's more important that ticks are no less than 16ms apart.Double frames
The
throttleToNextFramehelper could previously double-raf its callback.Previously, the
tickfunction puts itsflushcall behind a raf so that it occurs on the next frame. However, combined with the logic for enforcing the FPS, this meant thattick()could be delayed first by "too soon" raf, then again by the "next frame" raf, even though the "too soon" raf also would satisfy the "are we on the next frame" requirement.Normal healthy behavior :
Problem behavior. Because tick2 was "between ticks", it got delayed to frame 3, and then again to frame 4; from the perspective of its called, it should have run on frame 3.
This is presuming that
throttleToNextFrameis really about the next frame and not about the next tick, which I think is correct.But why
I was looking at how tldraw recovered from long frames, and digging deeper into the performance tab, I was seeing ticks where I wasn't expecting them: either adjacent to other ticks (with less than 16ms between them) and then not in other places.
Change type
bugfixTest plan
Release notes