Benchmarks
Every number on this page is read from one file, the raw results of the
latest full run of make compare, the comparison anyone can rerun (how). The site’s build
generates this page, the README’s headline numbers and the home page from it, and fails on a number that is not
read from it. Each figure is the mean ± σ (n) over the blocks of the run, σ the sample standard deviation; two
figures differ when their gap is more than 2σ = 2·√(σ₁²/n₁ + σ₂²/n₂).
The run
Section titled “The run”| When | 2026-10-29 17:16 UTC, 151 minutes |
| Command | make compare (tools/compare/compare.sh), the full mode |
| Code | release 1.0.0, its published image quay.io/oxidestack/docx-to-pdf:1.0.0@sha256:a752ca8f27bf24fc704c1ab078afa22c3616d78cf8913e655939ae2a63d60609, built from commit 0f45e85403477f2e70138eae3055ae6dbc70c277 |
| Host | Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz (x86_64), 8 vCPUs seen as 1 socket × 8 cores, 1 thread a core, 3000 MHz reported; caches L1d 32K, L1i 32K, L2 1024K, L3 36608K; 31.3 GiB; Ubuntu 24.04.5 LTS, kernel 6.8.0-147-generic, Docker 29.9.2, cgroup v2; a virtual machine under VMware, so the vCPUs’ pinning to the host’s cores is not visible from the guest |
| The speed cell | 1 pinned vCPU, a pool of 1, 16 GiB and /tmp on the host’s disk a service; a closed load of the typical reports report-img30-10mb, report-img45-12mb, report-img60-15mb, report-img60-20mb; 52 conversions a cell after a warm-up; 3 blocks, each running every cell once in a shuffled order (seed 1793294188) |
| The torture cases | each case at 12 GiB on vCPUs 2-3, each case waiting up to 300 s; soaks of 3000 conversions (1000 for moalhaddar/docx-to-pdf) alongside |
Speed and memory
Section titled “Speed and memory”Against oxidestack/docx-to-pdf
Section titled “Against oxidestack/docx-to-pdf”Each service’s figure over oxidestack/docx-to-pdf’s, the ratio of the means ± its standard error, from the same interleaved run. A ratio measured inside one run holds from one host to the next better than an absolute figure.
Where Gotenberg wins
Section titled “Where Gotenberg wins”Gotenberg is the generalist, and on its own ground nothing here competes with it: HTML and URLs to PDF, merging and splitting PDFs, PDF/A and PDF/UA, webhooks, clients in many languages and years in production. A team that needs those should use it. In this run, the rows where it is ahead of oxidestack/docx-to-pdf:
- Gotenberg, no restarts, written a conversion, MB: 27.9 ± 0.2 (3) against 28.3 ± 0.2 (3) (the row)
- Gotenberg,
png-g-32767(the same answer, 200, and the same pictures): answered in 9.78 s against 11.34 s, one run a side (the row) - Gotenberg, as shipped, LibreOffice’s resident memory over the soak’s second half: 289 ± 61 MiB over 1350 conversions against 391 ± 1 MiB over 1500 conversions, one soak a side (the row)
- Gotenberg, no restarts, LibreOffice’s resident memory over the soak’s second half: 347 ± 65 MiB over 1500 conversions against 391 ± 1 MiB over 1500 conversions, one soak a side (the row)
And the rows where neither is ahead at 2σ:
- Gotenberg, as shipped, written a conversion, MB: 28.3 ± 0.001 (3) against 28.3 ± 0.2 (3) (the row)
The torture test
Section titled “The torture test”Hostile and borderline documents, one run a side, each service as it ships: the answer, its time, the container’s memory peak and, for a picture, how many pictures reached the PDF. Judged by the answer: the times and peaks have no σ.
LibreOffice’s resident memory after each conversion of the typical reports, one soak a side: the first tenth, the second half, and the least-squares slope.
| Service | Soak |
|---|---|
| oxidestack/docx-to-pdf | 3000, 0 errors; LibreOffice RSS 390 ± 1 MiB (300 requests) over the first tenth / 391 ± 1 MiB (1500 requests) over the second half; +0.6 ± 0.0 MiB per 1000 over the last nine tenths, +0.5 ± 0.1 over the second half; floor 3.9 MiB per 1000 (1 % of the level): does not grow |
| Gotenberg, as shipped | 3000, 0 errors; LibreOffice RSS 287 ± 57 MiB (270 requests) over the first tenth / 289 ± 61 MiB (1350 requests) over the second half; +1.4 ± 1.6 MiB per 1000 over the last nine tenths, +6.0 ± 3.8 over the second half; floor 2.9 MiB per 1000 (1 % of the level): does not grow |
| Gotenberg, no restarts | 3000, 0 errors; LibreOffice RSS 326 ± 64 MiB (300 requests) over the first tenth / 347 ± 65 MiB (1500 requests) over the second half; +24.6 ± 1.5 MiB per 1000 over the last nine tenths, +55.0 ± 3.6 over the second half; floor 3.5 MiB per 1000 (1 % of the level): grows |
| moalhaddar/docx-to-pdf | 1000, 0 errors; LibreOffice RSS 304 ± 75 MiB (100 requests) over the first tenth / 329 ± 56 MiB (500 requests) over the second half; +30.3 ± 7.9 MiB per 1000 over the last nine tenths, -26.9 ± 17.4 over the second half; floor 3.3 MiB per 1000 (1 % of the level): levels off |
Earlier runs
Section titled “Earlier runs”The README and the comparison guide quote a ratio, a time or a peak as the range over this run and the earlier full runs of the same command on the same kind of machine, whose raw results are these:
- 2026-10-27 13:57 UTC, the code of that day, built by the command
- 2026-10-28 10:06 UTC, the code of that day, built by the command
Versions
Section titled “Versions”| Image | |
|---|---|
| oxidestack/docx-to-pdf | quay.io/oxidestack/docx-to-pdf:1.0.0@sha256:a752ca8f27bf24fc704c1ab078afa22c3616d78cf8913e655939ae2a63d60609@sha256:a752ca8f27bf24fc704c1ab078afa22c3616d78cf8913e655939ae2a63d60609 |
| k6 | grafana/k6:2.3.0@sha256:9c2dee7f8ed74d317e4027c06a10f169b625638189de8d4555d0b3486a5aeb34 |
| bench tools | docx-to-pdf-bench-tools:dev@sha256:dc17e88e7d905b0256e60246ae148c1a89d2e542c1e0b91112fa01dc96713ae8 |
| torture driver | python@sha256:f6a589d43c42b9e7f7dc67a12d37132491f362859a5d750607710cc56da3bc72 |
| Gotenberg | gotenberg/gotenberg:8.38.1@sha256:aa552cc115db488e0f0bcb07446aac13071ad51505b642c84bb894500907b42b |
| moalhaddar/docx-to-pdf | docker.io/moalhaddar/docx-to-pdf@sha256:14497d940936fe346cf74ce9c65bfa1eaff71487371888bd864777fd63a386c3 |
Documents
Section titled “Documents”Generated with fixed seeds, or fetched by commit; each one’s SHA-256:
| Document | SHA-256 |
|---|---|
report-img30-10mb |
276d4381cac57c10c75b2652056fe489361594a0576ee13647039161d992d6d1 |
report-img45-12mb |
b5c57826505addc85686b17243f0e9364298a48b10d398604b8332c4b3909cd6 |
report-img60-15mb |
059b0fb786d307e23dde3a817af64dff6086eb4eb1a948d9cc215be1fde68f3c |
report-img60-20mb |
a7eb5a7a35f71291c1c1ce99d756022659207cd53d2d3ae482cbb1e23ce4cd31 |
report-text-2p |
14cc062cc71317d906db044e13fa2373b1f3a7760023dbf2cb5227088ef95edd |
report-text-5p |
4b5bb5dbf8cc307d8226e6be1f12656f1affc17ff04dc3ac50de221416d00adc |
report-text-20p |
630e3075e50260601535459dfaa46f090c47b7d7ed18cb0836754a6610c38521 |
pages-500000p |
436e472ddd6c164dd973fb2d71a273b756444d2842a3ae60e63ce63bcd6b79ec |
px-8x1024mpx |
5dbb3b0237bfc88864fbe7ed410b4a4e34705be997cbc2dd285e8d2b01214020 |
tables-10000 |
2c4747fdc298d205edc0776df7c518ed9b27f52ef2f3a82570931128b59d9b76 |
png-g-32767 |
dc15106876878c782bd7ad361a173c76f194dd21f1e5bd1988905fa54f38fa41 |
png-g-32768 |
82310258bb2128cfc6750ad481a13143f0e6960b78be1df6d28c78710c593c61 |
png-rgb-18918 |
3f8a9a612418348332562181b83adf0355a23d9f5ee575da99aff6f8ea4df662 |
png-rgb-18919 |
e7270a6451eeb6dc8e2bf45bfdfec11c1d960d6c3b163f6466051762ed9289e6 |
empty |
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 |
random-1mb |
8e5525eaf28c03c578860c70ee5dc5adc65a87ad451f05d2c09536b429dad983 |
random-10mb |
9b73c366dd182d40010695058c2aedced35d262a136ff3c8c31280ac4d12e151 |
tdf38575 |
c6d022b650e67cb5281cfc71083dab16930d5515ef9ff78fe54d7c04ed9debaf |
Run it yourself
Section titled “Run it yourself”Docker is all it needs; a quick mode prints both tables in minutes on a laptop, and moalhaddar/docx-to-pdf, built for amd64 only, is skipped on another architecture:
git clone --recursive https://github.com/oxidestack/docx-to-pdf.git && cd docx-to-pdfmake compare QUICK=1 # minutes on a laptopmake compare # the full mode, as aboveexamples/compare/ says what each mode runs. The run writes the tables
and a results.json like this one.