mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-27 20:26:48 -06:00
Saving a large workbook spent about half its time building worksheet XML, mostly in small per-cell allocations. The writer now appends to the part directly: - Cell references, row numbers, style ids, shared string indexes and numbers are appended without temporary strings (push_a1, push_u64, push_num), and text is escaped in place (push_esc, with a fast path for plain ASCII). - sheetData walks the cell store in its own row-major order instead of copying every address into a BTreeSet and a per-row BTreeMap and looking each cell up again. Cells outside the store (pictures, spill values, table headers) still go through the sorted set. - Formulas with nothing the file spells differently (no LET/LAMBDA, no _xlfn function, no spill, @, trim operator or structured reference) are printed from the shared expression instead of being cloned and rebuilt twice by the file rewrite. - The A1 printer in gridcraft-formula appends references to the output instead of formatting each anchor into its own string. The output is byte-for-byte unchanged. write_perf, 200,000 rows (2.0M cells, 14.2 MB package), release, Ryzen 16 threads / Linux, 36 interleaved runs each: before: median 2083.9 ms, min 1615.7 ms after: median 1501.3 ms, min 1192.3 ms (-28.0 % median, -26.2 % min) What remains is mostly deflate (zlib-rs, level 6), about 70 % of the save. Tests pin the exact sheetData of a workbook covering row settings between cell rows, spill values, every value kind, number spellings, escaping and formulas with and without a file spelling (generated with the previous writer), and check each appending helper and the formula fast path against the code they replace. The formula fast path is guarded by a test that runs both paths over every function in the gridcraft-functions registry (a new dev-dependency, allowed by the layer rules), in 15 surrounding shapes covering every operator and rewrite, so a function or rewrite added later without updating the trigger list fails it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>