Benchmarks
tally-core ships two benchmarks. Each one fails when the mean latency of a case goes over its budget.
packages/core/src/grid/stress.bench.ts runs against 100,000 generated rows with 50 columns of every built-in type.
packages/core/src/execute/executor.bench.ts runs the executor against 100,000 rows with five columns. Filter and sort, group with an aggregate, three facets and a search each stay under 250 ms.
The numbers are budgets, not measurements. Run the benchmarks on your own hardware for real timings.
The stress dataset
The playground has a developer dataset at#/stress. It generates 100,000 rows with 50 columns in the browser and serves them from an in-memory array source: pinned and wide columns, enum pills, avatars, sparklines, meters, relative dates and footer aggregates. Use it to feel scrolling, sorting, grouping and filtering at that size.
Virtualization
tally-react virtualizes rows and columns with TanStack Virtual. Only the visible rows, plus six above and below, and the visible columns, plus two on each side, are in the DOM. Pinned columns and pinned rows stay mounted. The cards layout is virtualized too.
Where queries run
The grid sends each query to its data source and computes locally only what the source cannot do. Pick the source by where the rows live.Work the grid does locally only sees loaded rows. For large tables, use a source that filters,
sorts and groups on the server.
Loading
Live updates
Patches update rows in place. Under a sort, changed rows move to their new position without a reload. That is thepatch 1k rows with live sort case above. See Live updates.
Rendering in React
The hooks read the engine throughuseSyncExternalStore. useGridState and useView take a selector, and a component re-renders only when the selected value changes.
status.tsx
renderers, editors and labels stable across renders. Define them outside the component or memoize them, so cells do not re-render for nothing.