Large-file receipts
openpyxl slow or out of memory on a large file: the measured numbers
Every number on this page comes from one committed benchmark run of the pinned public packages, wolfxl 2.0.1 and openpyxl 3.1.5, with the raw results file and the harness published in the open-source repository. Reproduce it before you rely on it.
Why large workbooks hit a wall
openpyxl materializes a Python object per cell. A 200,000-row, 8-column sheet is 1.6 million cells, so a plain read or save spends its time constructing and serializing Python objects, and an in-place edit rewrites the whole package. WolfXL Community keeps the same openpyxl-style API but moves parsing, serialization, and cell storage into Rust.
Timings from the committed run
Median of 5 rounds per case, identical workload shape for both libraries. Full tables, including the small-workbook cases with smaller wins, are in the published results file.
| Workload | openpyxl 3.1.5 | wolfxl 2.0.1 | Ratio |
|---|---|---|---|
| Read every value, 200,000 rows x 8 columns (1.6M cells)load_workbook() and full row iteration; read family | 6.43 s | 0.60 s | 10.8x |
| Streaming read of the same 1.6M cellsread_only=True, iter_rows(values_only=True); read family | 4.89 s | 0.40 s | 12.1x |
| Write 1.6M cells to a new workbookws.write_rows() vs the same append loop shape; write family | 4.95 s | 0.48 s | 10.3x |
| Edit two cells in the 200,000-row workbook and savethe load-edit-save phase itself, excluding the verification reload | 18.43 s | 0.25 s | 73.3x |
The slow-save pain is the sharpest: the edit-and-save phase on the 200,000-row workbook took 0.25 s vs 18.43 s under openpyxl. Reloading the saved file to verify its contents costs the same in both libraries, and that verification reload is reported separately in the results file rather than hidden inside the ratio.
If the symptom is MemoryError
Peak resident set size, each case measured in its own fresh process. Baseline interpreter with both libraries imported is about 45 MiB.
| Workload | openpyxl 3.1.5 | wolfxl 2.0.1 | Peak ratio |
|---|---|---|---|
| Full read of 1.6M cells | 407.0 MiB | 146.6 MiB | 0.36x |
| Streaming read of 1.6M cells | 61.0 MiB | 47.1 MiB | 0.77x |
| Edit two cells and save, 200,000 rows | 516.1 MiB | 216.8 MiB | 0.42x |
On small workbooks the two libraries use roughly equal memory; the divergence is a large-file property. If a job dies inside a container limit, the streaming path is the first thing to try in either library.
Reproduce this on your machine
The recorded run used Python 3.13.9 on an Apple M4 Pro, macOS, on 2026-08-18. Different hardware produces different absolute times, which is why the harness, the raw results JSON, and the charts are committed and regenerated rather than edited.
python -m venv .bench && .bench/bin/pip install wolfxl==2.0.1 openpyxl==3.1.5
git clone https://github.com/SynthGL/wolfxl-community.git
.bench/bin/python wolfxl-community/benchmarks/benchmark_openpyxl_vs_wolfxl.py \
--rounds 5 --output-dir /tmp/wolfxl-bench --prefix my-runRead the harness source before trusting it: it runs matched workloads through the public APIs of both libraries and embeds machine, Python, and package versions in the output.
What does not get faster
- Small workbooks see much smaller wins than the large cases above.
- Reload-and-verify of a saved large file is roughly equal in both libraries.
- Peak memory on small workloads is roughly equal between the two libraries.
- Python-side transformation logic, storage latency, and delivery are unchanged; measure the workbook operation separately so the comparison stays honest.
- Unsupported operations fail as boundaries. Check the compatibility matrix before migrating a workload that uses less common openpyxl surface.
Try it on the failing job
WolfXL Community is MIT licensed and import-compatible for the documented API, so the trial is an install and an import change:
pip install wolfxl
# then
import wolfxl as openpyxl