Benchmarks · YAML
yeptris, the YAML engine
yeptris is the YAML counterpart of libleptris: a YAML 1.2 parser, emitter and streamer in C11 with hard memory bounds. The benchmark matrix runs both engines over the same corpora in the same process, across eight document shapes and three consumption models — DOM construction, pull parsing and event recording — in addition to emission. Every corpus is generated deterministically with a fixed seed, and the harness can dump each corpus so that any number on this page reproduces byte for byte.
| YAML — competitor | C / C++ | Ruby | Python | JavaScript | Rust |
|---|---|---|---|---|---|
| libyaml | 1.34×+ | — | — | — | — |
| ryml | 1.18×+ | — | — | — | — |
A green cell with a single value means every measured operation in that race is ahead, and the value shown is the smallest margin. A neutral cell shows the range from the weakest to the strongest operation; hovering lists the operations that remain behind. All rows, including deficits, appear in the tables below.
C
Versus libyaml
libyaml is the reference implementation underlying Ruby’s Psych and a large share of YAML tooling. The comparison below is the committed release gate: every shape and consumption model must stay ahead of the same-run libyaml measurement, and the weakest cell is the headline of each release.
| operation | leptris side | libyaml 0.2.5 | standing |
|---|---|---|---|
| Parse DOM — block heavy | 162.38 MB/s | 61.11 MB/s | 2.66× |
| Parse pull — block heavy | 90.9 MB/s | 61.11 MB/s | 1.49× |
| Parse recorder — block heavy | 107.32 MB/s | 61.11 MB/s | 1.76× |
| Emit — block heavy | 320.74 MB/s | 61.11 MB/s | 5.25× |
| Parse DOM — scalar heavy | 446.54 MB/s | 94.96 MB/s | 4.70× |
| Parse pull — scalar heavy | 292.15 MB/s | 94.96 MB/s | 3.08× |
| Parse recorder — scalar heavy | 326.5 MB/s | 94.96 MB/s | 3.44× |
| Emit — scalar heavy | 513.97 MB/s | 94.96 MB/s | 5.41× |
| Parse DOM — anchor heavy | 117.6 MB/s | 59.32 MB/s | 1.98× |
| Parse pull — anchor heavy | 79.43 MB/s | 59.32 MB/s | 1.34× |
| Parse recorder — anchor heavy | 90.83 MB/s | 59.32 MB/s | 1.53× |
| Emit — anchor heavy | 364.78 MB/s | 59.32 MB/s | 6.15× |
| Parse DOM — deep nesting | 501.6 MB/s | 155.56 MB/s | 3.22× |
| Parse pull — deep nesting | 249.2 MB/s | 155.56 MB/s | 1.60× |
| Parse recorder — deep nesting | 330.64 MB/s | 155.56 MB/s | 2.13× |
| Emit — deep nesting | 466.52 MB/s | 155.56 MB/s | 3.00× |
| Parse DOM — wide mapping | 248.67 MB/s | 70.48 MB/s | 3.53× |
| Parse pull — wide mapping | 133.45 MB/s | 70.48 MB/s | 1.89× |
| Parse recorder — wide mapping | 163.67 MB/s | 70.48 MB/s | 2.32× |
| Emit — wide mapping | 387.26 MB/s | 70.48 MB/s | 5.49× |
| Parse DOM — realworld suite | 70.42 MB/s | 44.05 MB/s | 1.60× |
| Parse pull — realworld suite | 61.18 MB/s | 44.05 MB/s | 1.39× |
| Parse recorder — realworld suite | 73.59 MB/s | 44.05 MB/s | 1.67× |
| Emit — realworld suite | 251.81 MB/s | 44.05 MB/s | 5.72× |
fresh runyeptris 0.6.22 (main f4b6e55)·min-of-iters; h2h rows: interleaved, median of rounds·GitHub Actions ubuntu-latest, x86_64 (AVX2)··bench_matrix — same corpus both engines, same run; h2h rows: interleaved head-to-head, median of rounds; simdjson parses a pre-built padded string (calibrated, #420)
Versus rapidyaml
rapidyaml is a C++ YAML parser with a substantially different internal design, and the comparison against it is run as an interleaved head-to-head with a fair ordering referee, reporting the median of rounds. The numbers on this page come from the Linux CI runner, where the AVX2 kernels dispatch: all five YAML shapes are ahead — block-heavy 1.61×, wide-mapping 1.80×, anchor-heavy 1.44× (the shape the ledger once named the open target), scalar-heavy 1.23×, deep-nesting 1.18×. The ARM macOS leg is the mixed read, and it is tracked with the same discipline. Every optimization attempt on these rows is recorded in the ledger with before-and-after numbers, including the attempts that measured flat and were reverted.
| operation | leptris side | ryml 0.16.0 | standing |
|---|---|---|---|
| Head-to-head DOM — block heavy | 158.16 MB/s | ryml 0.16.0 (f8ac8dd) | 1.61× |
| Head-to-head DOM — scalar heavy | 441.62 MB/s | ryml 0.16.0 (f8ac8dd) | 1.23× |
| Head-to-head DOM — anchor heavy | 133.68 MB/s | ryml 0.16.0 (f8ac8dd) | 1.44× |
| Head-to-head DOM — deep nesting | 508.81 MB/s | ryml 0.16.0 (f8ac8dd) | 1.18× |
| Head-to-head DOM — wide mapping | 245.05 MB/s | ryml 0.16.0 (f8ac8dd) | 1.80× |
The recorded residual is leg-specific: the NEON macOS runner reads closer to parity on several shapes than the AVX2 leg above, and that difference is tracked rather than smoothed over — the campaign logs treat an unexplained ISA gap as a defect. The discipline file for this work is theyeptris performance ledger. The JSON-shaped corpora in the same matrix are presented on theJSON page.
To reproduce: configure yeptris with-DYEPTRIS_BUILD_BENCHMARKS=ON -DYEPTRIS_BENCH_LIBYAML_ROOT=…(and -DYEPTRIS_BENCH_RYML_ROOT=… for the head-to-head), then run bench_matrix --full. The harness is committed atbenchmarks.
YAML
Measured deficits
Every YAML operation in the result data that remains behind its competitor, ordered from the weakest ratio. The current campaign carries none — the first refresh in the page's history where that is true — and the ARM-leg parity reads closest to the line stay tracked in the ledger rather than celebrated here.