Skip to content

Performance and delivery evidence

Freshness-gated benchmark and package-size evidence for Sheetwrite.
On this page

Every number on this page comes from a validated local protocol artifact captured on a clean tree; nothing is published from an unvalidated or protocol-mismatched artifact. Every expected cell carries either a validated timing or its recorded failure - a run that did not complete is shown as a failure, never converted into a timing.

Release retained engine memory

WebAssembly linear memory grows but does not shrink after cells or stores are cleared. When your application is idle after a large import, clear, or workbook disposal, call releaseEngineMemory explicitly. Sheetwrite never schedules a release automatically.

Explicit idle memory release
import { releaseEngineMemory } from "@sheetwrite/core";
const report = await releaseEngineMemory();

The call waits for synchronous transactions and active datasource page loads, then moves all live stores together into a fresh instance of the selected engine. Cell sources, styles, cached formula results (including volatile results), resident datasource pages, unsaved dirty edits, and compact undo/redo history survive. Unloaded clean pages remain unloaded and can be fetched again from the datasource. Worker renderers rebuild their frames without document-change events.

The main-thread pause scales with resident cells and compact history, so do not invoke it on an interaction-critical path. Migration temporarily needs both instances and packed transfer buffers; it can increase peak memory before garbage collection reclaims the retired instance. If preparation fails, every live store stays on the original instance. Concurrent calls share the same release.

report.wasmBytesBefore and report.wasmBytesAfter are committed linear-memory bytes, not live-cell bytes or process memory. report.pauseMs measures migration, excluding the idle wait. A release is not guaranteed to reduce committed bytes: surviving data, compact history, and migration scratch can still require substantial memory. Actual process-memory reclamation depends on garbage collection.

Capture

Captured
2026-10-17 05:18 → 2026-10-17 08:11 UTC
Commit
49e05e298c3f clean worktree
Artifacts
7 validated captures from that one commit; each section states its own environment (browser or runtime) and protocol

bench:release captures render-scale, the performance showcase's paged storage at bench/results/paged-results.json, the interaction evidence at bench/results/interaction-results.json, data, core paths, formula, formula engines, matched engines, and XLSX, then re-records the render regression baseline last. Its smoke rehearsal writes only to bench/results/smoke/.

The interaction capture (bench:interaction, schema interaction-current-v2) measures the current build, not a comparison: packed inverse-index lookup latency in nanoseconds, inverse-index backing bytes, retained bytes after 100 distant edits, and the cold-route long task owned by Sheetwrite. It records the raw samples, the summary derived from them, the runner, and the method, and it holds those four metrics to absolute release ceilings. Version 1 recorded a one-off before/after pair whose baseline build cannot be re-measured at a later release, so no old sample is carried forward into the current capture.

Matched local regression check

Timing comparisons run deliberately on a controlled local machine, not as a required CI job. Capture ten fresh matched rounds, retain every raw sample, and compare the fresh artifact with the committed baseline. Any unapproved slowdown fails the local command.

Zero-regression benchmark
bun run --filter @sheetwrite/bench bench:render:prepare
cd bench
bun run src/render-driver.ts --rounds 10 --output results/render-fresh.json --markdown-output results/render-fresh.md
bun run src/check.ts --baseline results/render-baseline.json --fresh results/render-fresh.json --power-mode balanced --concurrency 1

A result is a regression decision only when that final baseline check passes on the declared power mode and concurrency. bench:verify remains a smoke and safety-ceiling check.

The committed baseline at bench/results/render-baseline.json pins the harness source hashes, the declared sampling, and the runner (OS, CPU, Bun, Node, Chromium, power mode, concurrency). It is therefore machine- and harness-pinned: it must be re-recorded whenever a harness file, the sampling flags, the protocol version, or the runner changes, and the release capture does that as its last step by re-recording ten controlled rounds into bench/results/render-baseline-raw.json and promoting that artifact over the committed baseline. Until the re-recorded baseline is committed, bench:check fails closed on the fingerprint mismatch instead of comparing unrelated measurements.

Render benchmark

Validated evidence. 1120/1120 engine/scenario/round runs completed across 4 workbook sizes; every completed run passed its correctness checkpoints.

Both engines drive identical scripted interactions in a controlled browser. Pick a workbook size and a metric:

Captured
2026-10-17 05:18 UTC
Commit
49e05e298c3f clean worktree
Engines
Sheetwrite 0.5.0 release candidate · Handsontable 18.1.2
Environment
Bun 1.4.3 · Node compatibility 26.3.0 · Chromium 153.0.8010.12 · 12th Gen Intel(R) Core(TM) i9-12900H
Protocol
10 rounds · raw artifact bench/results/render-scale.json
interactionlog scale — every tick is 10× — shorter is fastermedianp95
scroll-down.top-left14.6× faster
Sheetwrite1.07 ms1.15 ms
Handsontable15.6 ms15.8 ms
scroll-down.middle4.0× faster
Sheetwrite1.02 ms1.08 ms
Handsontable4.02 ms4.13 ms
scroll-smooth.same-window21.4× faster
Sheetwrite0.39 ms0.42 ms
Handsontable8.28 ms8.34 ms
scroll-right.top-left43.3× faster
Sheetwrite0.26 ms0.30 ms
Handsontable11.3 ms11.5 ms
edit-open.top-left2.1× faster
Sheetwrite0.45 ms0.46 ms
Handsontable0.95 ms0.99 ms
edit-open.middle2.0× faster
Sheetwrite0.48 ms0.53 ms
Handsontable0.99 ms1.01 ms
edit-open.bottom-right3.5× faster
Sheetwrite0.40 ms0.45 ms
Handsontable1.40 ms1.42 ms
edit-commit.middle6.6× faster
Sheetwrite0.70 ms0.75 ms
Handsontable4.60 ms4.87 ms
altering.insert-5-rows-top6.5× faster
Sheetwrite0.83 ms0.91 ms
Handsontable5.40 ms5.70 ms
altering.remove-5-rows-top6.5× faster
Sheetwrite0.89 ms1.01 ms
Handsontable5.74 ms5.89 ms
arrow-down.top-left2.6× faster
Sheetwrite0.54 ms0.58 ms
Handsontable1.38 ms1.44 ms
arrow-right.middle2.3× faster
Sheetwrite0.56 ms0.58 ms
Handsontable1.25 ms1.32 ms
formatted-paint.top-left9.1× faster
Sheetwrite0.37 ms0.39 ms
Handsontable3.38 ms3.57 ms
merge-heavy.paint1112.4× faster
Sheetwrite4 µs4 µs
Handsontable4.02 ms4.09 ms
interactionrenderer heap after interaction — linear — shorter is leanerfootprintfaded = change
scroll-down.top-left1.5× leaner
Sheetwrite10.0 MB0.0 MB
Handsontable14.9 MB2.9 MB
scroll-down.middle1.5× leaner
Sheetwrite10.5 MB0.9 MB
Handsontable15.3 MB0.0 MB
scroll-smooth.same-window1.5× leaner
Sheetwrite11.0 MB0.4 MB
Handsontable16.4 MB3.7 MB
scroll-right.top-left1.2× leaner
Sheetwrite12.4 MB2.2 MB
Handsontable15.4 MB0.0 MB
edit-open.top-left1.7× leaner
Sheetwrite10.9 MB0.0 MB
Handsontable18.8 MB3.5 MB
edit-open.middle1.5× leaner
Sheetwrite11.1 MB0.7 MB
Handsontable17.0 MB1.3 MB
edit-open.bottom-right1.9× leaner
Sheetwrite11.0 MB0.4 MB
Handsontable20.7 MB1.1 MB
edit-commit.middle1.9× leaner
Sheetwrite12.5 MB2.4 MB
Handsontable23.6 MB7.9 MB
altering.insert-5-rows-top1.9× leaner
Sheetwrite12.4 MB0.5 MB
Handsontable23.1 MB0.6 MB
altering.remove-5-rows-top2.0× leaner
Sheetwrite12.0 MB0.2 MB
Handsontable23.3 MB8.6 MB
arrow-down.top-left2.1× leaner
Sheetwrite11.6 MB0.0 MB
Handsontable24.7 MB4.6 MB
arrow-right.middle1.8× leaner
Sheetwrite12.0 MB0.5 MB
Handsontable21.4 MB2.3 MB
formatted-paint.top-left2.5× leaner
Sheetwrite13.2 MB1.9 MB
Handsontable32.4 MB11.1 MB
merge-heavy.paint1.4× leaner
Sheetwrite15.3 MB0.3 MB
Handsontable22.2 MB0.0 MB
interactionlog scale — every tick is 10× — shorter is fastermedianp95
scroll-down.top-left14.2× faster
Sheetwrite1.10 ms1.14 ms
Handsontable15.6 ms15.6 ms
scroll-down.middle3.5× faster
Sheetwrite1.04 ms1.09 ms
Handsontable3.68 ms4.00 ms
scroll-smooth.same-window20.9× faster
Sheetwrite0.40 ms0.41 ms
Handsontable8.28 ms8.33 ms
scroll-right.top-left42.6× faster
Sheetwrite0.27 ms0.31 ms
Handsontable11.5 ms11.6 ms
edit-open.top-left2.3× faster
Sheetwrite0.42 ms0.45 ms
Handsontable0.99 ms1.01 ms
edit-open.middle1.8× faster
Sheetwrite0.51 ms0.54 ms
Handsontable0.92 ms0.98 ms
edit-open.bottom-right3.3× faster
Sheetwrite0.41 ms0.44 ms
Handsontable1.34 ms1.40 ms
edit-commit.middle6.4× faster
Sheetwrite0.72 ms0.75 ms
Handsontable4.60 ms5.09 ms
altering.insert-5-rows-top6.5× faster
Sheetwrite0.90 ms1.10 ms
Handsontable5.83 ms6.12 ms
altering.remove-5-rows-top6.4× faster
Sheetwrite0.92 ms1.02 ms
Handsontable5.83 ms6.03 ms
arrow-down.top-left2.5× faster
Sheetwrite0.56 ms0.59 ms
Handsontable1.39 ms1.43 ms
arrow-right.middle2.4× faster
Sheetwrite0.55 ms0.58 ms
Handsontable1.33 ms1.54 ms
formatted-paint.top-left9.3× faster
Sheetwrite0.37 ms0.39 ms
Handsontable3.48 ms3.56 ms
merge-heavy.paint1049.8× faster
Sheetwrite4 µs4 µs
Handsontable3.76 ms3.79 ms
interactionrenderer heap after interaction — linear — shorter is leanerfootprintfaded = change
scroll-down.top-left1.5× leaner
Sheetwrite11.0 MB0.0 MB
Handsontable16.8 MB4.1 MB
scroll-down.middle1.5× leaner
Sheetwrite11.3 MB0.9 MB
Handsontable17.3 MB0.9 MB
scroll-smooth.same-window1.5× leaner
Sheetwrite12.3 MB1.3 MB
Handsontable18.8 MB1.4 MB
scroll-right.top-left1.2× leaner
Sheetwrite13.4 MB2.3 MB
Handsontable15.6 MB0.5 MB
edit-open.top-left1.5× leaner
Sheetwrite11.2 MB0.0 MB
Handsontable17.3 MB2.1 MB
edit-open.middle2.2× leaner
Sheetwrite10.7 MB0.4 MB
Handsontable23.7 MB9.1 MB
edit-open.bottom-right2.1× leaner
Sheetwrite11.6 MB1.2 MB
Handsontable24.5 MB5.8 MB
edit-commit.middle1.4× leaner
Sheetwrite14.3 MB2.1 MB
Handsontable20.2 MB0.0 MB
altering.insert-5-rows-top3.3× leaner
Sheetwrite12.9 MB0.8 MB
Handsontable42.3 MB22.0 MB
altering.remove-5-rows-top4.0× leaner
Sheetwrite12.3 MB0.0 MB
Handsontable49.6 MB6.6 MB
arrow-down.top-left3.3× leaner
Sheetwrite11.7 MB0.0 MB
Handsontable38.2 MB7.3 MB
arrow-right.middle3.7× leaner
Sheetwrite12.0 MB0.6 MB
Handsontable43.9 MB5.4 MB
formatted-paint.top-left3.6× leaner
Sheetwrite14.2 MB2.8 MB
Handsontable51.7 MB5.1 MB
merge-heavy.paint2.3× leaner
Sheetwrite18.0 MB2.2 MB
Handsontable42.0 MB7.5 MB
interactionlog scale — every tick is 10× — shorter is fastermedianp95
scroll-down.top-left13.8× faster
Sheetwrite1.12 ms1.18 ms
Handsontable15.5 ms15.8 ms
scroll-down.middle3.9× faster
Sheetwrite1.04 ms1.11 ms
Handsontable4.06 ms4.27 ms
scroll-smooth.same-window20.7× faster
Sheetwrite0.40 ms0.41 ms
Handsontable8.28 ms8.33 ms
scroll-right.top-left41.0× faster
Sheetwrite0.28 ms0.31 ms
Handsontable11.4 ms11.5 ms
edit-open.top-left2.2× faster
Sheetwrite0.44 ms0.48 ms
Handsontable0.97 ms1.01 ms
edit-open.middle1.9× faster
Sheetwrite0.52 ms0.58 ms
Handsontable1.01 ms1.04 ms
edit-open.bottom-right3.4× faster
Sheetwrite0.42 ms0.47 ms
Handsontable1.43 ms1.46 ms
edit-commit.middle7.0× faster
Sheetwrite0.73 ms0.80 ms
Handsontable5.08 ms5.19 ms
altering.insert-5-rows-top8.2× faster
Sheetwrite1.70 ms1.79 ms
Handsontable13.9 ms15.6 ms
altering.remove-5-rows-top8.9× faster
Sheetwrite1.42 ms1.69 ms
Handsontable12.7 ms13.6 ms
arrow-down.top-left2.4× faster
Sheetwrite0.58 ms0.62 ms
Handsontable1.40 ms1.45 ms
arrow-right.middle2.3× faster
Sheetwrite0.58 ms0.62 ms
Handsontable1.32 ms1.37 ms
formatted-paint.top-left8.7× faster
Sheetwrite0.40 ms0.43 ms
Handsontable3.52 ms3.61 ms
merge-heavy.paint931.0× faster
Sheetwrite4 µs4 µs
Handsontable3.39 ms3.67 ms
interactionrenderer heap after interaction — linear — shorter is leanerfootprintfaded = change
scroll-down.top-left2.2× leaner
Sheetwrite20.8 MB0.0 MB
Handsontable45.4 MB2.7 MB
scroll-down.middle1.8× leaner
Sheetwrite17.3 MB0.7 MB
Handsontable31.8 MB0.0 MB
scroll-smooth.same-window1.7× leaner
Sheetwrite22.2 MB5.3 MB
Handsontable37.3 MB9.0 MB
scroll-right.top-left1.4× leaner
Sheetwrite22.3 MB5.2 MB
Handsontable32.0 MB0.4 MB
edit-open.top-left2.2× leaner
Sheetwrite17.6 MB0.0 MB
Handsontable38.8 MB6.2 MB
edit-open.middle2.5× leaner
Sheetwrite17.7 MB0.8 MB
Handsontable45.2 MB4.9 MB
edit-open.bottom-right2.4× leaner
Sheetwrite17.4 MB0.5 MB
Handsontable41.4 MB2.2 MB
edit-commit.middle2.5× leaner
Sheetwrite18.6 MB0.9 MB
Handsontable45.6 MB4.0 MB
altering.insert-5-rows-top7.0× leaner
Sheetwrite20.7 MB2.7 MB
Handsontable145.3 MB103.6 MB
altering.remove-5-rows-top8.9× leaner
Sheetwrite19.8 MB0.8 MB
Handsontable175.3 MB27.6 MB
arrow-down.top-left5.9× leaner
Sheetwrite18.4 MB0.3 MB
Handsontable108.5 MB0.0 MB
arrow-right.middle5.7× leaner
Sheetwrite18.2 MB0.9 MB
Handsontable103.7 MB0.0 MB
formatted-paint.top-left4.2× leaner
Sheetwrite21.0 MB2.2 MB
Handsontable88.7 MB4.3 MB
merge-heavy.paint3.5× leaner
Sheetwrite28.2 MB0.0 MB
Handsontable99.1 MB7.7 MB
interactionlog scale — every tick is 10× — shorter is fastermedianp95
scroll-down.top-left12.7× faster
Sheetwrite1.22 ms1.24 ms
Handsontable15.4 ms15.7 ms
scroll-down.middle4.0× faster
Sheetwrite1.02 ms1.44 ms
Handsontable4.14 ms4.61 ms
scroll-smooth.same-window20.7× faster
Sheetwrite0.39 ms0.40 ms
Handsontable8.11 ms8.28 ms
scroll-right.top-left42.9× faster
Sheetwrite0.27 ms0.39 ms
Handsontable11.4 ms11.5 ms
edit-open.top-left2.4× faster
Sheetwrite0.43 ms0.61 ms
Handsontable1.01 ms1.04 ms
edit-open.middle1.6× faster
Sheetwrite0.65 ms0.94 ms
Handsontable1.01 ms1.14 ms
edit-open.bottom-right3.1× faster
Sheetwrite0.41 ms0.62 ms
Handsontable1.26 ms1.38 ms
edit-commit.middle5.8× faster
Sheetwrite0.82 ms0.99 ms
Handsontable4.75 ms4.80 ms
altering.insert-5-rows-top8.2× faster
Sheetwrite11.8 ms12.0 ms
Handsontable97.2 ms103.3 ms
altering.remove-5-rows-top7.2× faster
Sheetwrite11.8 ms12.0 ms
Handsontable84.5 ms89.6 ms
arrow-down.top-left2.3× faster
Sheetwrite0.57 ms0.75 ms
Handsontable1.30 ms1.53 ms
arrow-right.middle2.4× faster
Sheetwrite0.55 ms0.79 ms
Handsontable1.31 ms1.33 ms
formatted-paint.top-left7.1× faster
Sheetwrite0.48 ms0.55 ms
Handsontable3.40 ms3.46 ms
merge-heavy.paint949.8× faster
Sheetwrite4 µs4 µs
Handsontable3.40 ms3.45 ms
interactionrenderer heap after interaction — linear — shorter is leanerfootprintfaded = change
scroll-down.top-left2.3× leaner
Sheetwrite105.5 MB0.0 MB
Handsontable240.7 MB20.6 MB
scroll-down.middle2.8× leaner
Sheetwrite75.0 MB0.0 MB
Handsontable207.9 MB0.0 MB
scroll-smooth.same-window2.1× leaner
Sheetwrite98.7 MB23.7 MB
Handsontable206.3 MB0.0 MB
scroll-right.top-left2.2× leaner
Sheetwrite93.4 MB0.0 MB
Handsontable205.1 MB10.0 MB
edit-open.top-left2.7× leaner
Sheetwrite79.4 MB0.0 MB
Handsontable212.4 MB12.8 MB
edit-open.middle2.7× leaner
Sheetwrite73.4 MB0.0 MB
Handsontable201.0 MB5.3 MB
edit-open.bottom-right2.6× leaner
Sheetwrite77.8 MB4.3 MB
Handsontable202.7 MB8.7 MB
edit-commit.middle2.5× leaner
Sheetwrite80.8 MB3.3 MB
Handsontable204.4 MB1.2 MB
altering.insert-5-rows-top11.3× leaner
Sheetwrite84.0 MB8.2 MB
Handsontable945.5 MB745.9 MB
altering.remove-5-rows-top6.9× leaner
Sheetwrite89.8 MB6.5 MB
Handsontable622.5 MB32.8 MB
arrow-down.top-left7.2× leaner
Sheetwrite76.5 MB0.0 MB
Handsontable553.9 MB0.0 MB
arrow-right.middle7.0× leaner
Sheetwrite77.3 MB0.0 MB
Handsontable537.4 MB0.0 MB
formatted-paint.top-left7.0× leaner
Sheetwrite79.5 MB0.7 MB
Handsontable557.7 MB17.3 MB
merge-heavy.paint4.6× leaner
Sheetwrite90.9 MB0.0 MB
Handsontable418.7 MB2.9 MB
Every bar in a panel shares the ruler's scale (speed is logarithmic - each tick is 10x), so lengths compare across rows as well as within them. Bright numbers are the median run; faded numbers are the p95 run (speed) or the interaction's heap delta (memory). Rows marked as not completed are runs the engine could not finish - the recorded failure (crash, timeout, or failed correctness checkpoint) lives in the raw artifact.
Methodology - what each scenario does

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-left
From the origin, jump-scroll 50 px down: a fresh row band enters the viewport and must paint.
scroll-down.middle
The same 50 px jump starting from the vertical middle of the scroll range.
scroll-smooth.same-window
Scroll 1 px without changing the visible row window: pure repaint cost, zero new data.
scroll-right.top-left
Jump-scroll 50 px right: a fresh column band paints.
edit-open.top-left
Select a cell near the origin and open its editor.
edit-open.middle
Open the editor on the center cell of the workbook.
edit-open.bottom-right
Open the editor on the last row and column - the far end of every index.
edit-commit.middle
Commit a typed value into the center cell and paint the result.
altering.insert-5-rows-top
Insert five rows at the top: every following row reindexes.
altering.remove-5-rows-top
Remove those five rows again - the inverse reindex.
arrow-down.top-left
Move the selection one cell down with the arrow key, including the selection overlay repaint.
arrow-right.middle
Arrow-key selection move at the workbook center.
formatted-paint.top-left
Repaint a viewport dense with per-cell formatting.
merge-heavy.paint
Repaint a viewport dense with merged ranges; Sheetwrite additionally proves it builds exactly one merge revision index.

Reproduce and validate with:

Controlled render evidence
bun run --filter @sheetwrite/bench bench:render:prepare
bun run --filter @sheetwrite/bench bench:render:scale

Runtime resource ownership

The performance showcase at /showcases/performance#resource-ownership renders the public RuntimeResourceSnapshot protocol directly. It keeps exclusive-owner logical bytes, allocated capacity, WASM committed pages, and independent browser runtime observations in separate buckets; committed pages are never summed into live payload. Bulk-edit before/settled deltas use diffRuntimeResourcePhases and omit unchanged owners.

The UI and this reference share RUNTIME_RESOURCE_SCHEMA_VERSION. Detailed peak phases remain in the validated benchmark artifact rather than being presented as measurements from the visitor's browser.

String collection reclaims obsolete pool text and densely remaps surviving IDs. Automatic collection runs only at committed edit transaction barriers, never during painting or page loading, when dead arena/span storage exceeds 256 KiB and the surviving arena/span storage. Growth-based backoff avoids repeatedly scanning unchanged live data. Bulk clears and sheet removal request a new threshold check at the next commit.

compactStringStorage() explicitly collects unreachable text and trims growth slack outside an active mutation/page load. Raw IDs are valid only within stringPoolEpoch(); retain the epoch with projections and invalidate caches on a change, as described in the worker rendering guide. History snapshots own captured text. Persist resolved values, not pool IDs. Reclaimed Rust ownership does not imply that WebAssembly committed linear memory shrinks.

Reproduce and validate the full owner/operation matrix with:

Runtime resource evidence
bun run --filter @sheetwrite/bench bench:resource

Data engine benchmark

Validated evidence. Head-to-head store operations at the sizes both engines complete headlessly; Sheetwrite additionally scales to 1M rows below.
Captured
2026-10-17 05:24 UTC
Commit
49e05e298c3f clean worktree
Engines
Sheetwrite 0.5.0 release candidate · Handsontable 18.1.2
Environment
Bun 1.4.3
Raw artifact
bench/results/data-results.json
operationlog scale — every tick is 10× — shorter is fastermedianp95
ingest440.5× faster
Sheetwrite0.56 ms0.62 ms
Handsontable248.2 ms267.7 ms
windowRead17.8× faster
Sheetwrite6 µs0.01 ms
Handsontable0.11 ms0.12 ms
edit32.8× faster
Sheetwrite4.46 ms5.83 ms
Handsontable146.3 ms217.1 ms
sort728.5× faster
Sheetwrite0.16 ms0.21 ms
Handsontable113.8 ms128.9 ms
filter2258.1× faster
Sheetwrite0.02 ms0.05 ms
Handsontable45.4 ms50.8 ms
aggregate17.1× faster
Sheetwrite5 µs5 µs
Handsontable0.09 ms0.11 ms
operationlog scale — every tick is 10× — shorter is fastermedianp95
ingest478.6× faster
Sheetwrite4.87 ms6.03 ms
Handsontable2,330.4 ms4,259.9 ms
windowRead16.2× faster
Sheetwrite7 µs0.01 ms
Handsontable0.12 ms0.13 ms
edit150.1× faster
Sheetwrite3.57 ms4.84 ms
Handsontable535.3 ms1,181.4 ms
sort11379.1× faster
Sheetwrite0.22 ms0.25 ms
Handsontable2,484.8 ms2,571.9 ms
filter25557.3× faster
Sheetwrite0.04 ms0.04 ms
Handsontable907.5 ms1,477.1 ms
aggregate20.3× faster
Sheetwrite0.04 ms0.04 ms
Handsontable0.77 ms0.87 ms

Sheetwrite alone at scale — Handsontable cannot complete these sizes headlessly:

operationlog scale — every tick is 10× — shorter is fastermedianp95
ingest
100k rows53.6 ms54.5 ms
500k rows284.4 ms284.6 ms
1M rows565.1 ms568.2 ms
windowRead
100k rows8 µs0.01 ms
500k rows0.01 ms0.01 ms
1M rows0.01 ms0.01 ms
edit
100k rows4.19 ms5.02 ms
500k rows3.84 ms4.18 ms
1M rows3.94 ms4.34 ms
sort
100k rows2.59 ms2.83 ms
500k rows12.6 ms13.1 ms
1M rows26.9 ms26.9 ms
filter
100k rows0.40 ms0.42 ms
500k rows1.88 ms1.92 ms
1M rows3.59 ms3.72 ms
aggregate
100k rows0.42 ms0.45 ms
500k rows1.90 ms1.97 ms
1M rows4.28 ms4.39 ms
Methodology - what each operation does

Identical columnar datasets, per-operation warmup and iteration plans. Fresh instance per ingest; window reads rotate offsets to defeat caches; sort and filter reset between runs; Handsontable edits run with rendering suspended so only its data path is timed.

Memory = JS-heap delta around one ingest in an isolated subprocess, plus Sheetwrite's WASM linear-memory delta.

ingest
Load the full dataset into a fresh engine instance.
windowRead
Read a 50x5 cell window at a rotating offset that sweeps the whole sheet.
edit
1,000 single-cell edits.
sort
Sort by the numeric amount column.
filter
Substring filter over the city column.
aggregate
Numeric aggregation over the amount column.

Reproduce with:

Data engine evidence
bun run --filter @sheetwrite/bench bench:data

Core write path

Validated evidence. 12 store and document scenarios at production sizes. Every scenario passed its own correctness checkpoint before its timing was accepted.
Grid.applyTransaction of a 1,000,000-cell setBlock
488.7 ms
fromCsv import of 200,000 rows by 10 columns
234.6 ms
undo of a 1,000,000-cell clearRange
1,609.1 ms
cold initSheetwrite() through first store in a fresh Node process (7 processes)
4.24 ms
ScenarioOne timed iterationMedianp95
row-bridge-insertone addRows projection of 10,000 rows into a 1,000,000-row bridge5.95 ms6.30 ms
command-state-selectone 4,096-cell range selection on a framework-style grid6.71 ms8.84 ms
with-command-state-handlerVariant of command-state-select, measured in the same run6.71 ms8.84 ms
without-command-state-handlerVariant of command-state-select, measured in the same run5.07 ms5.75 ms
setblock-admissionone Grid.applyTransaction of a 1,000,000-cell setBlock488.7 ms503.5 ms
setblock-detailed-captureone Grid.applyTransaction of a 1,000,000-cell setBlock observed through a change listener with detailed capture564.4 ms568.2 ms
sync-offline-queueone grid commit admitted into an offline sync queue with no listeners0.67 ms0.80 ms
rebase-largeone rebase of a 100,000-cell block across 50 single-row inserts1.54 ms1.54 ms
validation-sparseone 100,000-cell sparse setRange with 100 rules outside the range168.9 ms169.4 ms
csv-importone fromCsv import of 200,000 rows by 10 columns234.6 ms235.3 ms
undo-large-clearone undo of a 1,000,000-cell clearRange1,609.1 ms1,621.4 ms
restore-near-ceilingone restoreBlock with 60000044 decoded bytes1,060.1 ms1,069.8 ms
paged-evicted-revisitone revisit of an evicted paged band: scroll back plus a fixed async settle floor (wall time is not the accept metric)5.86 ms6.97 ms
node-cold-initone cold initSheetwrite() through first store in a fresh Node process (7 processes)4.24 ms4.58 ms
All measurements
Captured
2026-10-17 05:24 UTC
Commit
49e05e298c3f clean worktree
Environment
Bun 1.4.3 · Node compatibility v26.3.0 · 12th Gen Intel(R) Core(TM) i9-12900H
Raw artifact
bench/results/core-paths-results.json

Scale

ParameterValue
bridgeRows1,000,000
bridgeInsertRows10,000
selectionRows64
selectionColumns64
blockRows1,000
blockColumns1,000
offlineCommits5,000
rebaseBlockRows1,000
rebaseBlockColumns100
rebaseInsertOperations50
sparseCells100,000
validationRules100
csvRows200,000
csvColumns10
clearRows1,000
clearColumns1,000
pagedRows200,000

Samples

ScenarioSamples
row-bridge-insert2
command-state-select10
with-command-state-handler10
without-command-state-handler10
setblock-admission3
setblock-detailed-capture3
sync-offline-queue5000
rebase-large3
validation-sparse3
csv-import2
undo-large-clear3
restore-near-ceiling3
paged-evicted-revisit3
node-cold-init6

Counters

Non-time evidence recorded by the same runs.

ScenarioCounterValue
row-bridge-insertbridgeRows1,000,000
row-bridge-insertinsertedRows10,000
command-state-selectselectedCells4,096
command-state-selectcommandStateEvents13
command-state-selectwithoutHandlerMedianMs5.073
setblock-admissionblockCells1,000,000
setblock-admissiontransactions4
setblock-detailed-captureblockCells1,000,000
setblock-detailed-capturetransactions4
setblock-detailed-capturecapturedChanges1,000,000
setblock-detailed-capturevalidatedCapturedChanges1,000,000
sync-offline-queuequeuedCommits5,005
sync-offline-queueadmittedOperations5,005
rebase-largeblockCells100,000
rebase-largeinsertOperations50
rebase-largeverifiedValues100,000
validation-sparsewrittenCells100,000
validation-sparselogicalRangeCells1,000,000
validation-sparsevalidationRules100
csv-importimportedRows200,000
csv-importimportedColumns10
csv-importverifiedCells2,000,000
csv-importinputChars20,888,985
undo-large-clearclearedCells1,000,000
undo-large-clearclears4
undo-large-clearrestoredCells1,000,000
undo-large-clearcompactRestores5
undo-large-clearpeakRssBytes1,143,246,848
restore-near-ceilingrestoredCells4,000,000
restore-near-ceilingdecodedBytes60,000,044
restore-near-ceilingpeakRssBytes1,509,625,856
paged-evicted-revisitrevisitedRows3
paged-evicted-revisitareColumnsFullyLoadedCalls108
paged-evicted-revisitevictionVisits3
paged-evicted-revisitpagedRows200,000
node-cold-initlargestHeartbeatGapMs3.73
node-cold-initminimalHeartbeatTicks1
node-cold-initfreshProcesses7

Correctness checkpoints

ScenarioCheckpoint
row-bridge-insertprojected delta is one row-structure insert with every created identity present in the bridge in order
command-state-selectselection covers 4096 cells and the command-state handler observes one event per selection
setblock-admissionevery setBlock is applied and every cell of the block holds the last written value
setblock-detailed-captureevery setBlock is applied and every cell of the block holds the last written value, and its change capture reports every cell's address, previous value, and new value exactly once
sync-offline-queueevery commit is applied, the queue holds every commit at server version 0, and capacity stays available
rebase-largethe block rebases without conflict, shifts down by exactly the inserted row count, keeps every source value, and leaves the caller's operations untouched
validation-sparseevery write is applied, probe cells hold the last written values, every rule is retained, and a rule violation is still rejected
csv-importrow count matches and every imported cell equals the source value for its row and column, including declared number/text types
undo-large-clearthe clear empties the block and the undos restore every original cell value
restore-near-ceilinga valid near-ceiling compressed restore applies its complete block
paged-evicted-revisitthe band is unloaded before each revisit, the revisit reloads it with the source values, and the revisit asks areColumnsFullyLoaded at least once; areColumnsFullyLoadedCalls per revisit is the accept metric
node-cold-initevery fresh process loads the module, produces the expected engine result, and reports a plausible heartbeat gap

Reproduce with:

Core write-path evidence
bun run --filter @sheetwrite/bench bench:core-paths

Formula engine benchmark

Validated evidence. 53 recalculation workloads across dependency shapes; every workload passed the protocol's safety ceilings.
Captured
2026-10-17 06:43 UTC
Commit
49e05e298c3f clean worktree
Raw artifact
bench/results/formula-results.json
workloadlog scale — every tick is 10× — shorter is fastermedianp95
countif-100k
100,000 cells1.13 ms1.16 ms
criteria-multi-range-edit
100,000 cells5.61 ms5.76 ms
criteria-range-edit
100,000 cells1.65 ms1.67 ms
cross-sheet-range-edit
1,000 cells0.52 ms0.54 ms
cycles
1,000 cells1.54 ms1.58 ms
diamond-edit
32 cells0.11 ms0.12 ms
distinct-range-edit
1,000 cells0.01 ms0.02 ms
error-propagation
1,000 cells0.81 ms1.30 ms
formula-constant-edit
100,000 cells0.03 ms0.04 ms
incremental-dependency-closure-edit
100,000 cells0.02 ms0.04 ms
independent-first-recompute
1,000 cells1.15 ms1.17 ms
10,000 cells5.18 ms5.47 ms
100,000 cells88.6 ms90.0 ms
independent-parse-load
1,000 cells1.07 ms1.27 ms
10,000 cells6.24 ms6.98 ms
100,000 cells62.8 ms64.8 ms
iterative-finance
1,000 cells3.72 ms3.86 ms
let-repeat
100,000 cells1.97 ms2.02 ms
let-reuse-edit
100,000 cells0.67 ms0.68 ms
linear-chain
8 cells0.02 ms0.04 ms
16 cells0.03 ms0.03 ms
32 cells0.05 ms0.05 ms
64 cells0.08 ms0.09 ms
lookup-range-edit
100,000 cells1.70 ms1.80 ms
percentile-covariance
100,000 cells3.71 ms3.80 ms
removed-sheet-ref
1,000 cells0.50 ms0.78 ms
shared-range-edit
1,000 cells0.55 ms0.59 ms
spill-filter-resize
100,000 cells25.3 ms26.3 ms
spill-sequence-admission
100,000 cells13.4 ms13.6 ms
sum-multi-range
100,000 cells4.45 ms4.97 ms
sumifs-3-criteria
100,000 cells7.59 ms7.94 ms
sumproduct-matrix-edit
100,000 cells1.95 ms1.97 ms
sumproduct-vector-edit
100,000 cells2.11 ms2.24 ms
text-lookup-many
1,000 cells2.43 ms4.09 ms
text-lookup-many-edit
1,000 cells2.26 ms2.39 ms
text-lookup-many-sorted
1,000 cells3.83 ms3.88 ms
text-lookup-many-sorted-edit
1,000 cells3.71 ms3.78 ms
topology-remove-add
10,000 cells9.50 ms9.70 ms
unicode-text-date-edit
1,000 cells1.17 ms1.30 ms
vlookup-many
1,000 cells1.28 ms1.35 ms
vlookup-many-edit
1,000 cells1.13 ms1.16 ms
vlookup-many-sorted
1,000 cells1.65 ms1.66 ms
vlookup-many-sorted-edit
1,000 cells1.52 ms1.54 ms
wide-fan-out-edit
1,000 cells0.38 ms0.40 ms
100,000 cells60.4 ms62.1 ms
xlookup-many
1,000 cells1.28 ms1.33 ms
xlookup-many-edit
1,000 cells1.14 ms1.20 ms
xlookup-many-sorted
1,000 cells1.83 ms1.98 ms
xlookup-many-sorted-edit
1,000 cells1.76 ms1.78 ms
scalar-edit-affects
0 affected3 µs4 µs
1 affected4 µs9 µs
1,000 affected0.37 ms0.38 ms
100,000 affected60.4 ms63.6 ms
Methodology - what each workload does

Each workload builds a fresh WASM cell-store of the named dependency shape and times the recalculation from one action - usually a single edit. Sizes are formula-cell counts; bright = median, faded = p95.

linear-chain
A chain A1 -> A2 -> ... -> AN; editing the head recomputes the full depth.
wide-fan-out-edit
One scalar feeds N dependent formulas; edit the scalar.
diamond-edit
Fan-out that reconverges (diamond graph); edit the apex.
shared-range-edit
N formulas aggregate one shared range; edit one cell inside it.
distinct-range-edit
Each formula owns its own range; one edit recomputes only its owner.
cross-sheet-range-edit
Summary-sheet formulas range over another sheet; edit the source.
scalar-edit-affects-N
One scalar edit invalidating exactly N dependents; N=0 touches an unrelated cell, so it prices pure dependency lookup.
topology-remove-add
Remove and re-add rows so the dependency graph itself changes shape.
cycles
Introduce a reference cycle; detection and cycle-error propagation.
removed-sheet-ref
Formulas referencing a deleted sheet must all degrade to reference errors.
error-propagation
An error value (=1/0) flows through every dependent.
criteria-range-edit
Criteria-style aggregation (SUMIF shape) over 100k cells; edit inside the criteria range.
lookup-range-edit
Lookup-shape formulas over 100k cells; edit inside the looked-up range.

Reproduce with:

Formula engine evidence
bun run --filter @sheetwrite/bench bench:formula

Default and full formula engines

Validated evidence. 8 shared workloads have 25 paired rounds per engine. The full engine also has 8 checked analysis workloads.
Shared workloads more than 5% slower on the full engine
0 of 8
Widest paired-ratio spread
1.32× (limit 1.50×)
Default engine WASM, Brotli
256,150 B
Full engine WASM, Brotli
344,260 B

The default engine is @sheetwrite/wasm. The full engine is @sheetwrite/formulas. Select it with initSheetwrite(undefined, formulas). Each app uses one engine.

No shared workload tested in the matched rounds had a median paired ratio more than 5% slower with the full engine. This check covers the eight flagged rows, not a new matched run of all 53 rows.

Shared workloadSizeDefault medianFull medianPaired ratioRatio p10–p90
independent-parse-load1,0000.68 ms0.67 ms1.01×0.85×–1.12×
independent-first-recompute1,0000.64 ms0.54 ms0.92×0.77×–0.98×
independent-parse-load10,0006.72 ms6.57 ms0.94×0.87×–1.09×
independent-first-recompute10,0006.44 ms5.27 ms0.85×0.76×–0.93×
linear-chain80.01 ms0.01 ms0.95×0.84×–1.09×
wide-fan-out-edit1,0000.38 ms0.35 ms0.93×0.79×–1.02×
scalar-edit-affects-01,0001 µs1 µs1.00×0.95×–1.06×
vlookup-many1,0001.59 ms1.44 ms0.91×0.85×–1.02×
All measurements
Matched capture
2026-10-17 06:44 UTC
Matched commit
49e05e298c3f clean worktree
Analysis capture
2026-10-17 06:44 UTC
Analysis commit
49e05e298c3f clean worktree
Machine
12th Gen Intel(R) Core(TM) i9-12900H · Linux 7.2.8-1-cachyos · x64 · Bun 1.4.3

Method

The first capture ran all 53 shared workloads on each engine in sequence. Eight rows were more than 5% slower with the full engine. Those eight rows were checked with matched rounds. Each pair runs default, then full, in separate Bun processes. A timed sample starts with 3 untimed warm-up fixtures and then repeats the workload until at least 50 ms of measured time; the sample is the per-iteration mean, so a short operation is measured over many repetitions instead of one cold run. The runner used CPU 4 and one concurrent capture.

The ratio is full time divided by default time within each pair. The table shows the median of 25 paired ratios. The spread is the interpolated 10th to 90th percentile of those ratios. It is not a confidence interval. The time columns are the median times for each engine. A ratio below 1 means the full engine took less time.

Identical shared work is the control for this protocol: the widest paired-ratio p10–p90 span across the 8 rows is 1.32× (limit 1.50×), so each median ratio is supported by its paired samples.

Shared workloadIterations per sample
independent-parse-load64–84
independent-first-recompute70–101
independent-parse-load7–9
independent-first-recompute7–11
linear-chain4,177–5,658
wide-fan-out-edit117–161
scalar-edit-affects-081,154–96,796
vlookup-many28–40

Analysis workloads

Each workload has 1,000 formulas. It has one untimed warmup and five measured samples. Each sample uses a fresh store. The timer measures first recompute. Setup and output reads are outside the timer. Every result is read and summed as a checked checksum. The default engine does not run these analysis functions.

LINEST, SORTBY, and MAP/REDUCE use 100 input rows. DSUM uses 100 database rows, a header, and the criterion key > 0. XIRR uses two cash flows one year apart. The text workload uses three fields. MODE.MULT uses five scalar inputs. MMULT uses two 2-by-2 matrices. Array outputs are reduced to scalar results.

Full-only workloadMedianp95
linest4.66 ms7.70 ms
xirr1.54 ms1.60 ms
dsum2.98 ms4.16 ms
textsplit-regexreplace3.07 ms3.25 ms
sortby3.49 ms7.23 ms
mode-mult1.03 ms1.31 ms
map-reduce26.7 ms26.9 ms
mmult1.36 ms1.43 ms

WASM size and Node initialization

EngineNodeWASM bytesBrotli q11 bytesCold init medianCold init p95
defaultv26.9.0876,918256,1504.03 ms4.44 ms
fullv26.9.01,160,345344,2605.33 ms5.92 ms

Raw size is the WASM file size. Brotli size uses quality 11 on that file only. It is not the full package transfer size. Cold initialization uses five fresh Node processes. The timer surrounds initSheetwrite only. Imports and process startup are outside the timer. The operating system file cache is not cleared. No network download is measured. These samples do not establish that the full engine initializes faster.

Raw evidence: bench/results/full-engine-matched-results.json and bench/results/full-engine-results.json. They retain time samples, output checks, allocation samples, source hashes, and WASM hashes. The full workload captures are bench/results/formula-default-results.json and bench/results/formula-full-results.json. Their baseline gates stay blocked in output mode. A valid capture is not a passed timing regression gate.

The landing-page data comes from a separate browser benchmark. The Delivery size section below records published package sizes. Neither data set has an engine comparison field. They are unchanged by this local engine capture.

Reproduce after bun run build:packages:

Default and full engine evidence
cd bench
bun run bench:formula:engines
bun run bench:formula:matched

XLSX codec benchmark

Validated evidence. 5 compared operations over 5 process-isolated rounds each, from one checked corpus fixture.
Import: time
5.5× faster
Import: peak memory
91% less
Export, 4 scenarios: time
1.3–3.7× faster
Export, 4 scenarios: peak memory
19–47% less

The baseline is the same codec at commit 87fadb723979, built from that commit and measured in the same session. Ratio = current ÷ baseline; below 1 is faster or smaller.

OperationScenarioTime ratioPeak memory ratio
importcombined0.18×0.09×
exportscalar0.78×0.76×
exportrich0.69×0.80×
exportshared-style0.74×0.53×
exportsparse0.27×0.81×
All measurements
Captured
2026-10-17 08:11 UTC
Commit
49e05e298c3f clean worktree
Engines
Sheetwrite 0.5.0 release candidate · ExcelJS 4.4.0 at baseline 87fadb723979
Fixture
bench/fixtures/xlsx-codec-corpus.xlsx · 1,038,346 bytes · 2633e51a4a3c · LibreOffice 26.2.4.2 Calc MS Excel 2007 XML
Environment
Bun 1.4.3 · Node v26.3.0 · 12th Gen Intel(R) Core(TM) i9-12900H
Raw artifact
bench/results/xlsx-results.json
OperationScenarioCurrent medianBaseline medianCurrent peak RSSBaseline peak RSS
importcombined913.0 ms5,033.7 ms329.5 MB3642.2 MB
exportscalar300.9 ms384.5 ms165.3 MB217.2 MB
exportrich217.8 ms316.8 ms151.4 MB188.4 MB
exportshared-style534.8 ms724.2 ms163.0 MB307.6 MB
exportsparse27.5 ms102.4 ms97.0 MB120.1 MB

Reproduce with a checkout of the baseline commit, built and passed as the comparison root:

XLSX codec evidence
git worktree add ../sheetwrite-xlsx-baseline 87fadb72397947ea8c6ba576682925c7879579b8
cd ../sheetwrite-xlsx-baseline && bun install --frozen-lockfile && bun run build:packages
cd - && bun run --filter @sheetwrite/bench bench:xlsx -- --baseline-root ../sheetwrite-xlsx-baseline

Delivery size

Registry measurements for every published release. Each delta is measured against the release immediately before it.

v0.5.0v0.5.1
PackageTarballInstalled
@sheetwrite/wasm352.2 KiB+1.0 KiB+0.3%1002.6 KiB+5.5 KiB+0.6%
@sheetwrite/formulas471.1 KiB+908 B+0.2%1.26 MiB+5.6 KiB+0.4%
@sheetwrite/core348.8 KiB+8.4 KiB+2.5%1.62 MiB+29.8 KiB+1.8%
@sheetwrite/xlsx52.5 KiB+145 B+0.3%228.4 KiB+204 B+0.1%
@sheetwrite/react5.9 KiB+176 B+3.0%18.6 KiB+1.4 KiB+7.9%
@sheetwrite/vue6.9 KiB+250 B+3.7%21.5 KiB+920 B+4.4%
@sheetwrite/svelte5.9 KiB+287 B+5.0%16.2 KiB+974 B+6.2%
v0.4.0v0.5.0
PackageTarballInstalled
@sheetwrite/wasm351.1 KiB+63.2 KiB+21.9%997.1 KiB+204.3 KiB+25.8%
@sheetwrite/formulas470.2 KiB1.26 MiB
@sheetwrite/core340.5 KiB+38.3 KiB+12.7%1.59 MiB+175.1 KiB+12.0%
@sheetwrite/xlsx52.4 KiB-33.1 KiB-38.7%228.2 KiB-201.0 KiB-46.8%
@sheetwrite/react5.7 KiB-3.4 KiB-37.5%17.2 KiB-14.7 KiB-46.1%
@sheetwrite/vue6.7 KiB-3.5 KiB-34.2%20.6 KiB-15.1 KiB-42.4%
@sheetwrite/svelte5.6 KiB-613 B-9.6%15.3 KiB-3.2 KiB-17.2%
v0.3.1v0.4.0
PackageTarballInstalled
@sheetwrite/wasm287.9 KiB+390 B+0.1%792.8 KiB-2.8 KiB-0.3%
@sheetwrite/core302.1 KiB-215.3 KiB-41.6%1.42 MiB-1.29 MiB-47.6%
@sheetwrite/xlsx85.4 KiB-60 B-0.1%429.2 KiB-356 B-0.1%
@sheetwrite/react9.2 KiB0 B+0.0%31.9 KiB0 B+0.0%
@sheetwrite/vue10.1 KiB-2 B-0.0%35.7 KiB0 B+0.0%
@sheetwrite/svelte6.2 KiB0 B+0.0%18.5 KiB0 B+0.0%
v0.3.0v0.3.1
PackageTarballInstalled
@sheetwrite/wasm287.6 KiB0 B+0.0%795.6 KiB0 B+0.0%
@sheetwrite/core517.4 KiB+11 B+0.0%2.71 MiB+24 B+0.0%
@sheetwrite/xlsx85.5 KiB0 B+0.0%429.6 KiB0 B+0.0%
@sheetwrite/react9.2 KiB0 B+0.0%31.9 KiB0 B+0.0%
@sheetwrite/vue10.1 KiB0 B+0.0%35.7 KiB0 B+0.0%
@sheetwrite/svelte6.2 KiB0 B+0.0%18.5 KiB0 B+0.0%
v0.2.0v0.3.0
PackageTarballInstalled
@sheetwrite/wasm287.6 KiB+107.1 KiB+59.4%795.6 KiB+305.6 KiB+62.4%
@sheetwrite/core517.4 KiB+145.0 KiB+38.9%2.71 MiB+821.8 KiB+42.0%
@sheetwrite/xlsx85.5 KiB+10.5 KiB+14.0%429.6 KiB+63.5 KiB+17.3%
@sheetwrite/react9.2 KiB+2.2 KiB+31.2%31.9 KiB+9.9 KiB+45.0%
@sheetwrite/vue10.1 KiB+1.5 KiB+17.7%35.7 KiB+7.2 KiB+25.3%
@sheetwrite/svelte6.2 KiB+1,002 B+18.7%18.5 KiB+3.9 KiB+27.1%
v0.1.0v0.2.0
PackageTarballInstalled
@sheetwrite/wasm180.4 KiB+8.2 KiB+4.7%489.9 KiB+22.3 KiB+4.8%
@sheetwrite/core372.4 KiB+40.0 KiB+12.0%1.91 MiB+209.9 KiB+12.0%
@sheetwrite/xlsx75.0 KiB+53.7 KiB+252.2%366.1 KiB+273.1 KiB+293.7%
@sheetwrite/react7.0 KiB+30 B+0.4%22.0 KiB+134 B+0.6%
@sheetwrite/vue8.6 KiB-24 B-0.3%28.5 KiB-5.5 KiB-16.3%
@sheetwrite/svelte5.2 KiB+66 B+1.2%14.5 KiB+296 B+2.0%
v0.1.0
PackageTarballInstalled
@sheetwrite/wasm172.3 KiB467.6 KiB
@sheetwrite/core332.5 KiB1.71 MiB
@sheetwrite/xlsx21.3 KiB93.0 KiB
@sheetwrite/react7.0 KiB21.9 KiB
@sheetwrite/vue8.6 KiB34.0 KiB
@sheetwrite/svelte5.2 KiB14.2 KiB
IncreaseDecreasescripts/size-history.json
Documentation