-
Notifications
You must be signed in to change notification settings - Fork 1
Performance
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 |
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.
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:
- JSON serialization in Rust is heavily optimized (itoa, ryu)
-
JSON.parseis one of the fastest built-in JS operations - Avoids thousands of individual WASM boundary crossings
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.
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.
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;
}
}Use sheetRows to limit how many rows are parsed:
const first100 = sheetToJson(ws, { sheetRows: 100 });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');| Component | Size |
|---|---|
| WASM binary | ~939 KB |
| JS wrapper | ~55 KB |
| Total | ~994 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.
modern-xlsx v1.0.0
Getting Started
Guides
- Charts & Visualizations
- Formula Engine
- Table Layout Engine
- Tables & Print Layout
- Encryption
- Feature Comparison
Reference
Migration
Project