Loading documentation…
Loading documentation…
Both engines drive identical scripted interactions in a controlled browser. Pick a workbook size and a metric:
Live grid in controlled headless Chromium. Ten counterbalanced rounds; all fourteen scenarios run warm per mount, and the fixture is rebuilt after any failure so crashes cannot leak state. Every scenario must prove its effect (scroll really moved, editor really opened, rows really changed) or it fails.
Each measured sample repeats one logical action until it covers at least 100 ms of measured time, so timer resolution and scheduler jitter cannot decide a sample. Every raw sample is retained in the artifact.
Bright = median round, faded = p95 round. Did not complete = recorded crash, timeout, or failed checkpoint - never a timing. The failure table names the stage and the recorded error behind every missing cell.
scroll-down.top-leftscroll-down.middlescroll-smooth.same-windowscroll-right.top-leftedit-open.top-leftedit-open.middleedit-open.bottom-rightedit-commit.middlealtering.insert-5-rows-topaltering.remove-5-rows-toparrow-down.top-leftarrow-right.middleformatted-paint.top-leftmerge-heavy.paintReproduce and validate with:
bun run --filter @sheetwrite/bench bench:render:preparebun run --filter @sheetwrite/bench bench:render:scaleWith 2,000 literal-source charts, an outside-source edit takes 6.28 µs median / 10.27 µs p95, versus 6.74 / 16.51 µs with no charts. No chart is reported or resolved. Median cost does not rise proportionally across 200, 2,000 and 20,000 charts in this capture. This is not an asymptotic guarantee: the 20,000-chart p95 is 26.76 µs versus 11.13 µs without charts.
These are transaction-tracking costs, not SVG drawing or browser frame times. The no-chart control belongs to the same 0.6 capture, not an older release. Formula-backed sources refresh conservatively on value commits; their full costs and event counts remain visible below.
Event timings are omitted when no event is expected. Counts below are checked for every commit. Chart views are resolved only after the timer stops.
| Charts | Source | Edit | Expected events | Expected charts | Resolutions / commit |
|---|---|---|---|---|---|
| 200 | literal | outside | 0 | 0 | 0 |
| 200 | literal | inside | 1 | 1 | 1 |
| 200 | formula | outside | 1 | 200 | 200 |
| 200 | formula | literal-dependency-edit | 1 | 200 | 200 |
| 2000 | literal | outside | 0 | 0 | 0 |
| 2000 | literal | inside | 1 | 1 | 1 |
| 2000 | formula | outside | 1 | 2000 | 2000 |
| 2000 | formula | literal-dependency-edit | 1 | 2000 | 2000 |
| 20000 | literal | outside | 0 | 0 | 0 |
| 20000 | literal | inside | 1 | 1 | 1 |
| 20000 | formula | outside | 1 | 20000 | 20000 |
| 20000 | formula | literal-dependency-edit | 1 | 20000 | 20000 |
Each commit series contains 101 measured samples after 20 warmups.
Each chart reads two cells on its own row in one contiguous source region. Owners hold at most 100 charts per sheet. Inside edits change the second cell of chart 0's source and must report exactly that chart for literal sources. For formula sources, the row named literal-dependency-edit changes the literal second cell that chart 0's formula reads. The formula stays in place, so the index is not rebuilt. The conservative policy still reports every computed chart. A formula-replacement edit, which rebuilds the index, is not measured in 0.6. After each commit, an untimed check confirms the dependent formula value changed and the expected charts were reported. Outside edits occur after the source region. They must trigger no event or view resolution for literal sources. Both formula cases report every computed chart, so their cost can grow with chart count. View resolution and value checks run after the timer stops. Event latency ends on entry to the callback. Setup is untimed. Outside edits still query source-index blocks; a silent event stream is not a constant-cost guarantee.
Reproduce with:
bun run --filter @sheetwrite/bench bench:charts