feat: add raw_rows option for high-performance worksheet generation#8
feat: add raw_rows option for high-performance worksheet generation#8mbaertschi wants to merge 2 commits into
Conversation
Bypass the Cell protocol and XmlStream when `raw_rows: true` is passed to `Worksheet.new/4`, generating SpreadsheetML XML directly as iodata. Rows are processed in parallel batches via Task.async_stream, yielding ~4x speedup for large exports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Thanks for the contribution! I have a few thoughts:
Do you have benchmarks? I have personally tried and failed to improve the performance of xml_stream, so it would be nice to have a benchee example to try again with. |
|
Hei @sax Thanks for the feedback. Unfortunately I am under heavy pressure right now (for the project for which I created this PR :-)) I wont have time to work on this for like at least two weeks. In our case, this feature reduced the export time by the amount of available processes. For my local MacBook Pro from 40s to 8s, on k8s cluster from like 80s to 25s. The main benefit is parallel processing where number of concurrent processes is |
- Extract raw XML generation into Exceed.Worksheet.Raw module - Change raw_rows: true option to raw: true within opts (no separate struct field) - Add Benchee benchmark comparing normal vs raw: true modes
|
@sax any plans for this? |
|
I'm finally back to updating our open source, so I'm looking at this this week. I want to try a few things pulled from your changes first, to see if I can get the main path as fast as your version while preserving the functionality. |
|
Hey @mbaertschi, before I pull in your I also have this PR open in xml_stream: activesphere/xml_stream#5, which ekes out more throughput by combining two stream operations into one. I'm using the changes to binary pattern matching in that PR as overrides in exceed, so the main benefit of the PR is from the stream changes (if/when it merges, I'll remove some code from exceed). With everything combined, I'm seeing up to a 4.5x improvement in throughput for simple data types, with some slowdown for large binaries. In the benchmarks (exceed v0.7.3, with the xml_stream PR) on my M2, I see integers going from ~32k rows/sec to ~150k rows/sec. With all 10-20 character binaries, I see it go from ~19k/sec to ~55k/sec. When I change it to use |
|
Hei @sax so here are the numbers: My PR Exceed 0.7.3 Exceed 0.7.3 with xml-stream PR For me the v0.7.3 solution is already good enough, I'll close my PR. Thanks for your work! |
Bypass the Cell protocol and XmlStream when
raw_rows: trueis passed toWorksheet.new/4, generating SpreadsheetML XML directly as iodata. Rows are processed in parallel batches via Task.async_stream, yielding ~4x speedup for large exports.