Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Performance

ABCrimson edited this page Mar 2, 2026 · 4 revisions

Performance

Benchmarks

All benchmarks run on a 100,000-row, 10-column workbook. Node.js, single thread.

Operation modern-xlsx SheetJS CE Factor
Read 100K 1,155 ms 4,927 ms 4.3x faster
Write 100K 5,048 ms 5,048 ms 1.0x
aoaToSheet 50K 213 ms 341 ms 1.6x faster
sheetToJson 10K 54 ms 103 ms 1.9x faster
sheetToCsv 10K 83 ms 126 ms 1.5x faster

Why It's Fast

Rust WASM Core

The heavy lifting — ZIP decompression, XML parsing, shared string table lookup, and style resolution — runs in compiled WASM at near-native speed. The WASM sandbox also provides memory safety guarantees.

JSON Bridge

Data crosses the WASM boundary as a JSON string (serialized with serde_json in Rust, parsed with JSON.parse in JS). This is 8-13x faster than serde_wasm_bindgen for large workbooks because:

  1. JSON serialization in Rust is heavily optimized (itoa, ryu)
  2. JSON.parse is one of the fastest built-in JS operations
  3. Avoids thousands of individual WASM boundary crossings

SAX-Style XML Parsing

The Rust core uses quick-xml in SAX (streaming) mode rather than building a DOM tree. This keeps memory usage proportional to the current element being processed, not the entire document.

Inline SST Remapping

When writing, the shared string table is built and indices are remapped inline during XML generation — avoiding a full worksheet clone that earlier versions required.

Optimization Tips

Batch APIs

Use aoaToSheet / jsonToSheet instead of setting cells one by one:

// Fast — batch API
const ws = aoaToSheet(data);
// Slower — individual cell access
for (const [r, row] of data.entries()) {
 for (const [c, val] of row.entries()) {
 ws.cell(encodeCellRef(r, c)).value = val;
 }
}

Limit Rows on Read

Use sheetRows to limit how many rows are parsed:

const first100 = sheetToJson(ws, { sheetRows: 100 });

Initialize Once

Call initWasm() once at startup, not before every operation:

// Good
await initWasm();
// ...later, many operations...
// Bad — redundant (safe but wasteful)
await initWasm();
const wb1 = await readFile('a.xlsx');
await initWasm(); // unnecessary
const wb2 = await readFile('b.xlsx');

Bundle Size

Component Size
WASM binary ~870 KB
JS wrapper ~25 KB
Total ~895 KB

The WASM binary is loaded asynchronously and can be cached by the browser/runtime. The JS code is tree-shakable — unused utilities are eliminated by bundlers.

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /