Skip to content

pretable's interaction latency is ~2x TanStack's on S2 sort and filter #452

Description

@blove

Measured in #451 (status/milestones/2026-08-16-s2-mount-and-interaction.json), on a quiet machine, like-for-like on wrapping and pinning.

Interaction latency in ticks of a 120Hz frame, n=7 per cell:

script tanstack pretable
sort 2–5t (17–42ms) 6–8t (50–67ms)
filter-metadata 2–4t (17–33ms) 5–7t (42–58ms)
filter-text 1–4t (8–33ms) 6–7t (50–58ms)

pretable centres on 7 ticks (58ms), TanStack on 3–4 ticks (25–33ms). Consistent across three structurally different interactions and 21 repeats each, with barely overlapping distributions — so this is not the sampling artifact that invalidated the scroll medians in #450.

Where it probably is not

Rendering. pretable settles with the fewest DOM nodes of the four adapters:

pretable tanstack ag-grid mui
rendered rows at settle 7–8 6–7 16–18 11
DOM nodes at settle 100–107 294–335 474–506 1180

Doing the least DOM work and still losing to two of the three points at the row model — filtering and sorting 3,000 rows — rather than at paint.

What would settle it

A CPU profile sliced to the interaction window, which nobody has taken:

PLAYWRIGHT_PERF_TRACE=1 pnpm bench:matrix --adapters=pretable --scenarios=S2 --scripts=sort --scale=hypothesis --repeats=1

then node scripts/analyze-cdp.mjs <trace> <bundle>.js.map --window=interaction. Note the window flag: the full-trace view is dominated by mount work that does not count against interaction_latency_ms.

Worth knowing before optimising: #388 filed a scroll cost as an accuracy-vs-speed trade and the profile showed it was neither — it was redundant grapheme segmentation. The frame this issue names may likewise not be where it looks.

Caveat

interaction_latency_ms is frame-quantised, so pretable's 7 ticks and TanStack's 4 differ by three frames, not by "33ms" precisely. The gap is real and reproducible; the exact millisecond figure is not the thing to optimise against.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions