feat(bench): measure main-thread blocking on the interaction path - #461
Merged
Conversation
Closes #458. interaction_latency_ms latches the first changed rAF frame, and under that definition a synchronous engine that blocks the main thread for its whole sort and a cooperative one that never blocks were indistinguishable — the interaction path collected no long-task metric at all (the scroll and updates paths already did). Every comparative interaction table published so far was structurally blind to the one property pretable pays its latency premium for. The observer attaches AT the trigger, not at function entry: a long task during the pre-trigger quiet wait is mount tail, and charging it to the interaction would poison the metric. It is a push-based PerformanceObserver, so unlike the height-error walk removed in #456 it adds no per-frame DOM work. Emitted as post_interaction_long_tasks_count / _ms, absent (not zero) when the host cannot observe long tasks — the same absent-vs-zero rule as the row-height error. First measurement, S2 sort, 3 repeats each: 3,000 rows: pretable 0 long tasks | tanstack 0 (its ~15ms block is under the 50ms longtask threshold) 50,000 rows: tanstack reports ~33ms latency while blocking the main thread for 62ms (1 task, 3/3 runs, sd <1ms) The test plays synthetic entries into a stubbed observer at three moments — during the run's own quiet wait, inside the trigger, and asserts teardown. Mutation-checked: attaching at function entry, never disconnecting, and dropping the metrics each redden it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
Vercel preview readyPreview: https://pretable-87d86o85q-cacheplane.vercel.app Updated automatically by the |
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.
Closes #458. Step 1 of the #452/#457 sequence — instrument before tuning, so the next change (the slice-budget lever) can prove it didn't regress main-thread blocking rather than assert it.
What
measureRowSetChangenow runs alongtaskPerformanceObserver and emitspost_interaction_long_tasks_count/_ms. Until now the interaction path collected no blocking metric at all — the scroll and updates paths already did — so a synchronous engine blocking for its whole sort and a cooperative engine that never blocks were indistinguishable in every published interaction table.Three deliberate choices:
First measurement
S2 sort, 3 repeats each, quiet machine:
So the honest comparative statement is finally expressible: at target scale TanStack reports a 33ms latency while blocking the main thread for 62ms per sort. (pretable at 50k is #457 — it never blocks but currently can't complete inside the window.)
Verification
The test stubs
PerformanceObserver, plays synthetic entries at three moments — during the run's own quiet wait (via the frame stub'sonFrame, not merely before the call — that distinction is what catches an observer attached at entry), inside the trigger, and after completion — and asserts count, total, and teardown.Mutation-checked: attach-at-entry, never-disconnect, and metrics-dropped each redden the test. 156 bench tests, 16 bench-runner tests, typecheck, lint, format.
🤖 Generated with Claude Code