Skip to content

feat(bench): make the group script comparative against TanStack - #477

Merged
blove merged 1 commit into
mainfrom
blove/tanstack-grouping
Aug 17, 2026
Merged

feat(bench): make the group script comparative against TanStack#477
blove merged 1 commit into
mainfrom
blove/tanstack-grouping

Conversation

@blove

@blove blove commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

The bench-runner gate excluded TanStack from every grouping script on the claim that it "ships no row-grouping row model of its own." That was stale: the installed @tanstack/table-core 9.1.2 ships createGroupedRowModel, rowAggregationFeature and createExpandedRowModel in the free package. The grids whose grouping is genuinely paywalled are AG Grid (Enterprise) and MUI (Premium) — they stay excluded, on that stated ground.

What changed

  • tanstack adapter registers the grouping/expansion/aggregation features and row models — module scope, state-gated, the same shape as pinning (S2 comparators ignore pinned_left, so the pinned zone is pretable-only #413). A group plan derives grouping from plan.rowGroups, everything expanded; group rows carry the harness's row attributes so the settle signature treats them as rows.
  • Aggregation parity is the load-bearing detail: pretable's adapter deliberately attaches "avg" to every numeric column so the aggregation stage is costed, and TanStack's aggregation is lazy — a grouped render that never reads aggregated cells would skip the work and flatter it. Numeric columns get aggregationFn: "mean" and the group rows render the aggregate, forcing the computation inside the measured window.
  • The gate allows tanstack for group only. group-expand and the grouped streaming scripts stay pretable-only with the reason corrected to the truth — their setup/trigger run through pretable-specific machinery in bench-app.tsx (waitForGroupedRowModel, grid.rowModel.setGroupExpanded) — rather than the capability claim the old comment got wrong.

First comparative grouping numbers

S2 hypothesis, 5 repeats each, quiet machine (idle 88%):

status latency result rows long tasks
pretable completed 5/5 58–66ms 3004 ✓ 0
tanstack completed 5/5 15–26ms 3004 ✓ 0

Both land on exactly the plan-predicted count (3000 leaves + 4 groups), which is the settle detector's row-count check passing on the plan's own arithmetic — the grouped+expanded flat model and pretable's interleaved model agree. The ~2–3× latency pattern matches sort/filter (#452); grouping is now part of that same story rather than an untestable claim.

Verification

Both directions at the unit layer (group rows + rendered means with a plan; byte-identical ungrouped render without one), and the runner matrix test updated to the new contract — including asserting the tanstack group-expand rejection says "plumbing", because repeating the stale capability claim is exactly what the old test did.

Mutation-checked, each caught by the guard built for it:

mutation goes red
drop the aggregate (group without aggregating) the aggregate assertions
grouping state never derived the positive arm
grouping unconditionally on the negative arm
revert the gate the runner matrix test

158 bench tests, 16 runner tests, typecheck, lint, format.

Follow-up

group-expand comparator plumbing (a comparator-generic pre-window setup + toggle handle in bench-app) is filed separately — it's an app-machinery change, not an adapter one.

🤖 Generated with Claude Code

The bench-runner gate claimed "TanStack Table ships no row-grouping row model
of its own" and excluded it from every grouping script. That was stale: the
installed @tanstack/table-core 9.1.2 ships createGroupedRowModel,
rowAggregationFeature and createExpandedRowModel in the free package. The only
grids whose grouping is genuinely paywalled are AG Grid (Enterprise) and MUI
(Premium), and they stay excluded on that stated ground.

The tanstack adapter now registers the three features plus the grouped and
expanded row models — unconditionally at module scope, gated entirely by state,
the same shape as pinning (#413). A `group` plan derives `grouping` from
`plan.rowGroups` with everything expanded, which is the state the plan's
resultRowCount arithmetic (leaves + one group row per key) describes; group
rows render with the harness's own row attributes so the settle signature
treats them as rows.

Aggregation parity is the part that keeps the comparison honest: pretable's
adapter deliberately attaches an "avg" aggregate to every numeric column so the
aggregation stage is costed, and TanStack's aggregation is lazy — a grouped
render that never reads the aggregated cells would skip the work entirely and
flatter it. So numeric columns get `aggregationFn: "mean"` and the group rows
RENDER the aggregate, forcing the computation inside the measured window.

`group-expand` and the grouped streaming scripts stay pretable-only, and the
gate now states the real reason — their setup and trigger run through
pretable-specific machinery in bench-app.tsx — instead of the capability claim
the old comment got wrong.

First comparative run (S2 hypothesis, 5 repeats each, quiet machine): both
adapters complete with exactly the plan-predicted 3004 rows and zero long
tasks; pretable 58-66ms, tanstack 15-26ms — the same ~2-3x interaction pattern
as sort and filter (#452), now with grouping measured like-for-like.

Mutation-checked: dropping the aggregate, never deriving the grouping state,
grouping unconditionally, and reverting the gate each redden exactly the test
built to catch them. 158 bench tests, 16 runner tests, typecheck, lint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
pretable Ignored Ignored Aug 17, 2026 8:06pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

Vercel preview ready

Preview: https://pretable-mxa3emj0q-cacheplane.vercel.app
Commit: d2108c5591a87331f50bfd0328b886de09bca056

Updated automatically by the deploy-preview job.

@blove
blove merged commit 5f59f86 into main Aug 17, 2026
20 checks passed
@blove
blove deleted the blove/tanstack-grouping branch August 17, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant