The conversion benchmark

The full benchmark is incomplete for this release.

Completed lenses are shown below with their own identities. Older lenses remain reference values and are not presented as measurements of the current release.

Recorded benchmark lenses

Each lens retains its own version and revision. Values from different releases are shown for context but are not combined into one result.

Native CLI benchmark

Earlier reference native lens: zenfmt 0.3.3 at 45d9001. These values describe one modest reference machine.

Native CLI

Geometric means over the 14 files converted by zenfmt and AnyDoc.

Speed ratio6.9×AnyDoc wall time / zenfmt
CPU ratio7.9×AnyDoc CPU time / zenfmt
Peak memory ratio10.1×AnyDoc peak RSS / zenfmt

Docling uses parser-only backends. OCR, VLM, ASR, layout models, table models, enrichment, and accelerators are disabled. Unsupported files remain visible rather than switching to an AI pipeline.

ToolConvertedCorpus
zenfmt1616
Docling parser only516
AnyDoc1416
Pandoc616

Each ratio divides the comparison tool by zenfmt over shared successful files. Speed is elapsed wall time, CPU is user plus system processor time, and peak memory is resident set size. Above 1.0 means the comparison used more of that measure in this run. These ratios are context, not quality scores.

Comparison tool / zenfmtShared files SpeedCPU usePeak memory
Docling parser only / zenfmt5190.4×205.5×47.5×
AnyDoc / zenfmt146.9×7.9×10.1×
Pandoc / zenfmt618.2×16.5×16.6×

Long-running server benchmark

Earlier reference server lens: zenfmt 0.3.3 at 45d9001. These values describe one modest reference machine.

Long-running server, measured separately

Warm HTTP conversion against Apache Tika Server on the same host and corpus. These values are not mixed into the native CLI ratios.

Warm latency ratio31.1×Tika / zenfmt over 16 shared files
Peak memory ratio34.2×Tika / zenfmt sampled RSS
Throughput at 1 client552.7 / 4.4zenfmt / Tika documents per second
Startup0.11 / 6.97 szenfmt / Tika Server
Peak RSS53.0 / 1814.9 MiBparent and direct parser children
Corpus16 filesthe same verified manifest
Filezenfmt median msTika median mszenfmt p95 msTika p95 ms
article.pdf0.7620.540.85120.96
book.epub38.04861.2138.52902.74
data.csv50.73118.0651.07493.77
deck.ppt5.571744.865.931968.61
grid.xlsb0.4812.630.5225.24
letter.odt0.436.910.449.14
memo.doc0.38106.080.43153.63
notes.rtf0.628.140.6516.95
page.html33.1890.2933.54163.32
report.docx1.79231.261.84233.44
sheet.ods0.7412.390.7513.86
sheet.xlsx1.2913.471.3015.58
slides.odp13.642919.6013.832927.00
slides.pptx16.523045.4816.903186.91
spec.pdf0.339.420.3431.63
table.xls0.487.580.5010.59

Server throughput

Concurrent clientszenfmt documents/sTika documents/s
1552.74.4
21074.58.3
42015.614.3
82654.714.5

What is measured, and separately

Three questions are kept apart because they have different answers. Coverage is which files each tool claims and actually converts. Performance is cold startup and warm conversion latency, CPU time, and peak memory. Output preservation is checked per format against a tool-neutral fixture oracle, and is never collapsed into a single quality score.

Correctness before timing

The native and browser lenses admit timing only after their output checks pass. Their head-to-head comparisons use only shared successful files. The server lens has a smaller gate: a successful response with a nonempty body. It does not yet prove semantic quality or direct-to-server byte parity, so its timings should be read with that limitation.

Three lenses, never blended

Native process startup, warm library calls, WebAssembly download and compile, warm WebAssembly execution, and a long-running HTTP service answer different questions. The native, browser, and server lenses are therefore reported separately, with cold and warm measurements clearly labelled. A file a tool does not support is shown as unsupported, never as infinitely slow.

Reproducing it

The corpus is not redistributed here: it is assembled from third-party documents whose licences differ, and a conversion of one is a derivative work. What is published is each file's identity, format, size, SHA-256, and source, which is what a reader needs to fetch the same bytes. benchmarks/fetch_corpus.sh verifies every digest and refuses to proceed on a mismatch.