Benchmarks · JSON
JSON, through yeptris
yeptris parses JSON as what it is — a strict subset of YAML 1.2 — through a dedicated fused walk that validates the RFC 8259 grammar and builds the document in a single pass. Conformance is gated by the JSONTestSuite corpus under the YAML 1.2 schema, where yeptris accepts all 95 valid inputs and rejects all 188 invalid inputs. The measurements below race the JSON-shaped corpora through the committed benchmark matrix against the YAML incumbents and against simdjson, the reference JSON parser, in the same run. Two consumption routes are measured against simdjson: DOM construction, which builds a navigable document, and the tape route introduced in yeptris 0.2.2, which validates into compact parallel columns with no document model. The simdjson comparison is stated with both numbers and is the honest centerpiece of this page.
| JSON — competitor | C / C++ | Ruby | Python |
|---|---|---|---|
| libyaml | 2.24×+ | — | — |
| ryml | 0.89×+ | — | — |
| simdjson | 0.22×–0.36× | — | — |
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
yeptris versus the YAML incumbents
The matrix generates two JSON-shaped corpora: a multi-document flow-json corpus and a single-document flow corpus. Both are measured through DOM construction, pull parsing and event recording, in addition to emission, in the same run against the same-build reference libraries.
| operation | leptris side | libyaml 0.2.5 | standing |
|---|---|---|---|
| Parse DOM — flow json | 162.75 MB/s | 42.38 MB/s | 3.84× |
| Parse pull — flow json | 95.11 MB/s | 42.38 MB/s | 2.24× |
| Parse recorder — flow json | 104.85 MB/s | 42.38 MB/s | 2.47× |
| Emit — flow json | 131.3 MB/s | 42.38 MB/s | 3.10× |
| Parse DOM — flow single | 207.43 MB/s | 43.08 MB/s | 4.82× |
| Parse pull — flow single | 107.33 MB/s | 43.08 MB/s | 2.49× |
| Parse recorder — flow single | 117.79 MB/s | 43.08 MB/s | 2.73× |
| Emit — flow single | 149.96 MB/s | 43.08 MB/s | 3.48× |
| Parse DOM — json doc | 196.19 MB/s | 39.63 MB/s | 4.95× |
| Parse pull — json doc | 101.11 MB/s | 39.63 MB/s | 2.55× |
| Parse recorder — json doc | 111.69 MB/s | 39.63 MB/s | 2.82× |
| Emit — json doc | 353.05 MB/s | 39.63 MB/s | 8.91× |
fresh runyeptris 0.2.4 (main 9674b80)·min-of-iters (--full); ryml rows: interleaved, median of rounds·Apple M1 Max, macOS 14.1.1, arm64··bench_matrix --full — same corpus both engines, same run; vs ryml: interleaved head-to-head
Versus rapidyaml on the same corpora
| operation | leptris side | ryml 0.16.0 | standing |
|---|---|---|---|
| Head-to-head DOM — flow json | — | ryml 0.16.0 (f8ac8dd) | 0.92× |
| Head-to-head DOM — flow single | — | ryml 0.16.0 (f8ac8dd) | 0.89× |
| Head-to-head DOM — json doc | — | ryml 0.16.0 (f8ac8dd) | 0.96× |
The head-to-head against rapidyaml is run interleaved with a fair-order referee and reports the median of rounds. The yeptris performance ledger records the engine-dispatch work behind these rows, together with every measured dead end, in theyeptris ledger.
Versus simdjson, the JSON-native reference
| operation | leptris side | simdjson 4.6.1 | standing |
|---|---|---|---|
| Head-to-head parse — json-doc via DOM construction | 211.23 MB/s | simdjson 4.6.1 (3839ac6) | 0.22× simdjson validates into a linear tape with SIMD structural indexing and no document model; the tape route below is the JSON-native path that closes part of this gap |
| Head-to-head parse — json-doc via the tape route | 355.8 MB/s | simdjson 4.6.1 (3839ac6) | 0.36× the tape route validates into compact parallel columns with no document model — the JSON-native consumption path landed in 0.2.2; the remaining gap to simdjson is the walk itself |
simdjson validates JSON into a linear tape with SIMD structural indexing and no document model, which is a fundamentally cheaper contract than anything that also serves YAML. Through the DOM route yeptris measures at 0.22× simdjson; through the tape route, which dropped document construction the same way simdjson does, it measures at 0.36×. These deficits are stated rather than omitted, and the remaining gap on the tape route is the validation walk itself, which is the recorded objective of the continuing JSON work in the yeptris performance ledger. Applications that need a DOM, pull events, or emission in the same library are the audience these pages measure for.
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.
JSON
Measured deficits
Every JSON operation in the result data that remains behind its competitor, ordered from the weakest ratio. This section is generated from the same result files as the tables above.
| operation | leptris side | versus | standing |
|---|---|---|---|
| Head-to-head parse — json-doc via DOM construction | 211.23 MB/s | simdjson 4.6.1 (3839ac6) | 0.22× simdjson validates into a linear tape with SIMD structural indexing and no document model; the tape route below is the JSON-native path that closes part of this gap |
| Head-to-head parse — json-doc via the tape route | 355.8 MB/s | simdjson 4.6.1 (3839ac6) | 0.36× the tape route validates into compact parallel columns with no document model — the JSON-native consumption path landed in 0.2.2; the remaining gap to simdjson is the walk itself |