SHOWCASE / PERFORMANCE AND SCALE
One million rows, measured in front of you.
The grid below owns a paged datasource of exactly 1,000,000 deterministic rows. Live panels read the running engine through public APIs; committed numbers are benchmark artifacts with capture provenance. Protocol details live in the performance guide.
Booting the WASM engine…
Million-row paging
- Cells resident now
- 0
- Resident chunks
- 0
- Resident cache
- 0 B
- 0% of budget
- Dense equivalent
- 0 B
- Page requests
- 0
- Rows served / aborted
- 0 / 0
Full-dataset operations stay honest
Whole-dataset queries and exports refuse to fabricate unloaded rows. This expected bounded refusal returns a typed IncompleteDataError with exact loaded and total counts.
Wide pages
The second sheet is 121 columns wide and still paged — hydration is bounded by the visible window, never by the sheet.
- Rows × columns
- 250,000 × 121
- Served page
- 121 cols × 4,096 rows
- Loaded cells (live)
- 0
Activate the wide sheet to watch pages hydrate; its live counters share the stats strip above.
Cache churn under a byte budget
Clean chunks live inside a 8.0 MiB cache — far less than 24 deterministic long jumps across the million-row feed will touch.
Worker rendering with honest fallback
The paint backend is chosen at construction, and rendererKind() reports what actually constructed — never what was requested. See the Worker rendering guide.
WASM boundary crossings, counted
Cell state lives in Rust/WASM; bulk commits cross the JS↔WASM boundary a constant number of times per operation — not once per cell. Each button commits a real, undoable transaction over 20,000 cells.
Committed benchmark evidence
The numbers below were not measured in your browser — they are committed benchmark artifacts, reproduced verbatim with capture provenance from the repository's benchmark protocol (bench/README.md).
Paged storage protocol
Source bench/results/paged-results.json — paged-full-v1 (protocol v1, full mode, 12 runs), 1,000,000 rows × 5 columns, 120-row pages, 32.0 MiB cache budget.
| Measurement | Median | p95 |
|---|---|---|
| Startup (1M-row workbook) | 0.06 ms | 0.78 ms |
| First page visible | 0.34 ms | 0.98 ms |
| Distant page (long jump) | 0.32 ms | 0.48 ms |
| Peak allocated | 530.0 KiB vs 62.0 MiB dense logical | |
Scenario probes
| Scenario | Chunks | Loaded cells | Allocated | WASM Δ |
|---|---|---|---|---|
| empty | 0 | 0 | 0 B | 64.0 KiB |
| padding | 0 | 0 | 0 B | 64.0 KiB |
| viewport | 5 | 150 | 265.0 KiB | 320.0 KiB |
| scroll-1 | 15 | 50,000 | 795.0 KiB | 832.0 KiB |
| scroll-10 | 125 | 500,000 | 6.5 MiB | 6.6 MiB |
| scroll-100 | 618 | 2,513,728 | 32.0 MiB | 32.2 MiB |
| dirty | 100 | 100 | 5.2 MiB | 5.3 MiB |
Cross-grid comparison capture
Source docs/src/generated/landing-bench.json — captured 2026-07-16 on Chromium 149.0.7827.55, 10 rounds, commit 47f164385f.
| Rows | Scenarios compared | Median ratio | Best scenario |
|---|---|---|---|
| 1,000 | 14 | 7.2× | scroll-right.top-left (96.7×) |
| 10,000 | 14 | 10.7× | scroll-right.top-left (111.3×) |
| 100,000 | 14 | 26.3× | scroll-right.top-left (201.2×) |
| 1,000,000 | 12 (2 incomplete on Handsontable) | 130.3× | scroll-smooth.same-window (1522.2×) |
Live panels measure this very page — page latency is a deliberate 90 ms simulation so lazy loading stays visible. Live numbers and committed benchmark numbers are not comparable to each other, and are never mixed.