gp-grid-logo

Benchmarks

Compare gp-grid scroll, render, sort/filter and memory performance against popular data grid libraries on a 1,000,000-row dataset.

These benchmarks compare gp-grid against other popular data grid libraries on a single 1,000,000-row dataset, using an identical set of columns and the same seeded data for every grid. Each metric below is the median across repeated iterations. The exact machine, runtime and library versions used for this run are listed with the results so the numbers are reproducible.

Methodology

  • Same data, same columns. Every grid renders the same deterministically generated rows and columns; only the grid under test changes.
  • Windowed virtualization. All grids keep just the visible row window in the DOM. gp-grid caps its scroll container at 10,000,000px because browsers mis-render taller elements; above ~312,000 rows (at a 32px row height) the natural content height exceeds that cap, so gp-grid compresses the scroll space (a scroll ratio below 1) and maps the scrollbar position back to logical row coordinates. At 1,000,000 rows this compression is active. Grids that instead render a full-height spacer (row count ร— row height) rely on the browser's own maximum element-height limits.
  • Identical wheel input. The measured scroll sends the same synthetic mouse-wheel events to every grid. Each grid's scroll and virtualization model translates that input into a different travelled distance (custom scrollbars and dampened virtual-scroll wheel handling rescale the deltas), so instead of forcing an equal distance through grid-specific APIs, the tables report Rows Traversed โ€” how many rows each grid actually covered under the same input.
  • Mode column. Each table lists how a grid is wired up. native-grid is a shipped grid component; headless-table-virtualizer supplies only the data/virtualization model while the benchmark authors the DOM; app-side-virtual-data feeds a virtual data source from the benchmark. The Notes section below the results spells out the per-grid details.

Metrics Explained

MetricBetterDescription
Avg FPSHigherAverage frames per second during scroll (frames รท elapsed time)
P05 FPSHigher5th-percentile FPS โ€” the slow end of the distribution
P95 Frame TimeLower95th-percentile frame duration; lower means fewer long frames
Frame DropsLowerNumber of frames that took longer than 25ms
Rows Traversedโ€”Rows covered during the measured scroll (logical scroll delta รท row height) under the identical wheel input
Scroll Deltaโ€”Logical (content) pixels travelled during the measured scroll
Scroll px/sโ€”Logical pixels travelled per second during the measured scroll
FCPLowerTime to first contentful paint
Full RenderLowerTime until the grid is fully rendered and interactive
LCPLowerLargest Contentful Paint
TBTLowerTotal Blocking Time
After LoadLowerHeap size after the data is loaded
PeakLowerMaximum heap size observed during the run
Growth / 1KLowerHeap increase per 1,000 rows
RetainedLowerHeap not released after clearing the data
MinifiedLowerMinified production JS + CSS of the grid's packages, bundled with Vite (React/React DOM excluded)
GzipLowerThe same bundle after gzip compression

Run Details

  • Run: 2026-07-16T10-29-40-792Z
  • Date: 2026-07-16T10:29:40.796Z
  • Machine: Intel(R) Core(TM) Ultra 7 258V
  • Environment: win32 10.0.26200, 8 logical CPUs, 32244 MB RAM
  • Runtime: Node v24.14.0, Chrome 150.0.7871.116
  • Config: 10 iterations, 1 Playwright worker, retries 0, overscan 10 rows, 32px row height, 1280x720, headless true
  • Scope: DOM-rendering grids. Canvas-rendering grids are excluded: their painting model is not directly comparable.

Library Versions

GridPackageVersion
gp-grid@gp-grid/react0.19.0
ag-gridag-grid-community35.3.1
ag-gridag-grid-react35.3.1
tanstack-table@tanstack/react-table9.0.0-beta.16
tanstack-table@tanstack/react-virtual3.14.3
handsontablehandsontable17.1.0
smart-gridsmart-webcomponents-react26.0.0

Package Bundle Sizes

Production ESM JavaScript and CSS bundles of the exact grid-library imports used by each benchmark, minified by Vite and measured with gzip. React and React DOM peer dependencies are excluded; bundled transitive dependencies and imported CSS are included, while other emitted assets are excluded. Every package is sized at the published npm version shown in its Packages cell.

GridPackagesMinifiedGzip
gp-grid@gp-grid/react@0.19.0170.7 kB41.5 kB
ag-gridag-grid-community@35.3.1, ag-grid-react@35.3.11098.7 kB306.7 kB
tanstack-table@tanstack/react-table@9.0.0-beta.16, @tanstack/react-virtual@3.14.367.1 kB19.2 kB
handsontablehandsontable@17.1.01521.2 kB350.1 kB
smart-gridsmart-webcomponents-react@26.0.04082.6 kB779.7 kB

Scroll Performance

Every grid receives the identical mouse-wheel input. Each grid's scroll and virtualization model translates that input into a different distance (custom scrollbars and dampened virtual-scroll wheel handling rescale the deltas), so the Rows Traversed column shows how many rows each grid actually covered during the measured pass.

GridModeRowsAvg FPSP05 FPSP95 Frame TimeFrame DropsRows TraversedScroll DeltaScroll px/s
gp-gridnative-grid1M56.254.318.4ms050116026px934
AG Gridnative-grid1M41.8544.34999999999999427.15ms49156350000px2184.5
Handsontablenative-grid1M26.554248.95ms69.5156550080px1334
Smart.Gridapp-side-virtual-data1M56.654.918.2ms21595087px290.5
TanStack Tableheadless-table-virtualizer1M53.954.318.4ms2156350000px4088.5

Initial Render

GridModeRowsFCPFull RenderLCPTBT
gp-gridnative-grid1M1334ms1493.5ms1474ms1297ms
AG Gridnative-grid1M1348ms2530ms2430ms2153.5ms
Handsontablenative-grid1M388ms10202ms950ms9708.5ms
Smart.Gridapp-side-virtual-data1M172ms1359ms0ms921.5ms
TanStack Tableheadless-table-virtualizer1M600ms2171.5ms1736ms1875.5ms

Sort/Filter Performance

GridModeRowsSort AscSort DescMulti SortText FilterNumber Filter
gp-gridnative-grid1M652ms571.5ms1219.5ms188ms129.5ms
AG Gridnative-grid1M2104ms1620.5ms3044.5ms327ms281.5ms
Handsontablenative-grid1M33801.5ms33571ms45970.5ms2216.5ms1287ms
Smart.Gridapp-side-virtual-data1M1018ms523ms976.5ms191ms175.5ms
TanStack Tableheadless-table-virtualizer1M1193ms1073.5ms2530.5ms224ms243.5ms

Memory Usage

GridModeRowsAfter LoadPeakAfter ScrollGrowth / 1KRetained
gp-gridnative-grid1M254.73MB267.82MB255.32MB0.25MB0.81MB
AG Gridnative-grid1M461.94MB610.68MB463.36MB0.46MB1.97MB
Handsontablenative-grid1M941.42MB945.48MB942.32MB0.94MB1.31MB
Smart.Gridapp-side-virtual-data1M244.89MB247.82MB245.36MB0.24MB239.94MB
TanStack Tableheadless-table-virtualizer1M457.84MB481.44MB461.75MB0.46MB445.34MB

Notes

  • gp-grid: Above ~312,000 rows gp-grid caps its DOM scroll container at 10,000,000px, compresses the scroll space, and dampens wheel deltas before applying them, so the shared wheel input traverses fewer rows than on the natively-scrolling grids (see Rows Traversed). Below that threshold it scrolls natively via the wheel like the other grids. Its scroll delta is reported in logical (content) pixels.
  • Smart.Grid: Uses Smart.Grid virtualDataSource; sort/filter processing is performed by the benchmark adapter over the full in-memory dataset, then Smart.Grid renders the requested virtual window. Smart.Grid exposes no configurable row overscan, so the shared overscan setting does not apply to it. Its custom scrollbar rescales mouse-wheel input to fixed line steps rather than the event's delta, so under the shared wheel input it traverses a different number of rows than the natively-scrolling grids (see Rows Traversed).
  • TanStack Table: TanStack Table is headless: it supplies the sort/filter/row models and, with @tanstack/react-virtual, the row virtualization, but the row and cell DOM is authored by this benchmark. Its render and scroll numbers therefore reflect the benchmark's own markup, not a shipped grid component.

Reproduce

Clone gp-grid, then from the benchmarks/ directory:

pnpm install
pnpm bench

Optionally override the defaults with environment variables before pnpm bench:

  • BENCH_ROW_COUNTS โ€” comma-separated row counts (default 1000000)
  • BENCH_ITERATIONS โ€” iterations per grid (default 5)
  • BENCH_RUN_ID โ€” a label for the run's results directory

On this page