mirror of
https://github.com/nlohmann/json.git
synced 2026-11-04 11:49:22 +00:00
docs: compare json_document with Glaze, sonic, RapidJSON and Rust parsers
Extends the comparison in "How 3.13.0 got faster" from yyjson, simdjson and Boost.JSON to eleven engines: sonic-cpp, RapidJSON and Glaze (generic DOM, lazy_json, reading into structs) in C++, sonic-rs, simd-json and serde_json in Rust. Measured on an Apple M1 Max (Apple clang 21, Rust 1.99) and an x86-64 Haswell server (GCC 13, Clang 18). Every engine must return the same values, string bytes and bit-identical number sums before it is timed. The post now answers whether json_document is the fastest parser: it is the fastest document parser at parse+dump everywhere and at parsing on Apple silicon, ties with simdjson's DOM on x86-64, and loses to simdjson On-Demand and Glaze structs when only a few fields are read. tests/benchmarks/json_view/others holds the programs (bench_all.cpp, the Rust crate with its Cargo.lock), summarize.py and the pinned versions and checksums. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
9 files changed
+1987
-117
No files matched your search
@@ -8,9 +8,10 @@ Since 2016, the README of this library has said this about speed:
|
||||
That sentence is still true, but the gap is a lot smaller now. Swap the 3.12.0 header for the 3.13.0 one and recompile,
|
||||
and the 182 benchmarks of the library's suite run on average 2.9× as fast, without a line of your code changing.
|
||||
Parsing the 1.7 MB `citm_catalog.json` takes 1.75 ms instead of 7.20 ms, and `dump()` of documents made of objects
|
||||
and strings is 4.7 to 6.7× as fast. The new read-only [`json_document`](../../features/json_view.md) parses the
|
||||
usual test files faster than yyjson and simdjson's DOM on Apple silicon (with a caveat for float-heavy files that we
|
||||
explain below).
|
||||
and strings is 4.7 to 6.7× as fast. The new read-only [`json_document`](../../features/json_view.md) parses and
|
||||
writes faster than the other document parsers we measured on Apple silicon, including yyjson, simdjson and
|
||||
sonic-rs, and ties with simdjson on x86-64. It is not the fastest everywhere; [section 8](#8-build-a-different-data-structure)
|
||||
says where it loses.
|
||||
|
||||
This post is about *how*. None of the techniques is new: almost every one of them is borrowed from simdjson, yyjson,
|
||||
fast_float, Żmij, serde_json, SQLite, Boost.JSON or a textbook, and we name the source at each step. What we think is
|
||||
@@ -552,42 +553,77 @@ entries in document order instead of trees of separate allocations, and yyjson's
|
||||
returning the last one meant scanning every object to its end and made lookups in small objects 1.6 to 3.4 times
|
||||
slower ([#5622][5622]).
|
||||
|
||||
Parse times in µs on the M1 Max (C++17, `-O3`, best of 30 interleaved rounds; a fresh `json_document` and yyjson
|
||||
document each time, simdjson's parser reused as its documentation recommends):
|
||||
### How it compares
|
||||
|
||||
| file | `json_document` | yyjson 0.13.0 | simdjson 4.6.11 DOM | Boost.JSON 1.92.0 | `json::parse` |
|
||||
| --- | --: | --: | --: | --: | --: |
|
||||
| `twitter.json` (632 KB) | **182** | 192 | 216 | 866 | 1,368 |
|
||||
| `citm_catalog.json` (1.7 MB) | **360** | 478 | 490 | 1,480 | 2,409 |
|
||||
| `canada.json` (2.3 MB) | **960** | 1,489 | 2,098 | 2,501 | 5,890 |
|
||||
| `jeopardy.json` (56 MB) | **22,687** | 30,528 | 26,875 | 88,900 | 167,664 |
|
||||
We compared `json_document` with eleven other engines. In C++: yyjson 0.13.0, simdjson 4.6.11 (its DOM and its
|
||||
On-Demand API), sonic-cpp 1.0.2, RapidJSON (master, 24b5e7a), Glaze 9.0.0 (its `generic_u64` DOM, its `lazy_json`,
|
||||
and reading straight into structs), and Boost.JSON (1.92 on the Mac, 1.83 on x86-64). In Rust: sonic-rs 0.5.10, simd-json 0.19.0 and serde_json
|
||||
1.0.154. Plus `json::parse`. Before anything is timed, every engine must report the same number of values, the same
|
||||
number of string bytes, and a bit-identical sum of all numbers in document order. That means every engine converts
|
||||
every number exactly; RapidJSON guarantees that only with `kParseFullPrecisionFlag`, so that is what it runs with
|
||||
(with its default flags it happened to produce the same values for these files, and those rows are in the data).
|
||||
|
||||
The workloads: *parse* (build the document and free it), *traverse* (parse, then visit every value and convert every
|
||||
number), *select* (parse, then read a few fields of every record) and *parse+dump*. We ran them on the M1 Max with
|
||||
Apple clang 21 (and Rust 1.99), and on the x86-64 Haswell server with GCC 13 and Clang 18 (`-march=haswell`, one
|
||||
pinned core). That server has other work running, so differences of a few percent there are noise. Glaze 9 could
|
||||
not be built with Clang 18 on it (Clang 18 can't use GCC 13's `std::expected`), and the Rust engines ran on the Mac
|
||||
only.
|
||||
|
||||
Parse times in µs on the M1 Max, a fresh document each time (C++23 and Rust `--release`, `-O3`, best of 30
|
||||
interleaved rounds):
|
||||
|
||||
| engine | `twitter.json` (632 KB) | `citm_catalog.json` (1.7 MB) | `canada.json` (2.3 MB) | `jeopardy.json` (56 MB) |
|
||||
| --- | --: | --: | --: | --: |
|
||||
| `json_document` | **183** | **364** | **943** | **22,681** |
|
||||
| yyjson | 194 | 478 | 1,489 | 30,342 |
|
||||
| simdjson DOM | 202 | 486 | 2,097 | 26,904 |
|
||||
| sonic-rs (Rust) | 302 | 664 | 1,907 | 30,202 |
|
||||
| sonic-cpp | 379 | 986 | 2,580 | 40,804 |
|
||||
| simd-json (Rust, input copy included) | 567 | 1,616 | 4,939 | 59,364 |
|
||||
| Boost.JSON | 868 | 1,483 | 2,481 | 88,925 |
|
||||
| RapidJSON | 1,183 | 1,613 | 7,358 | 143,044 |
|
||||
| serde_json (Rust) | 1,202 | 2,337 | 6,836 | 139,829 |
|
||||
| Glaze `generic_u64` | 1,268 | 2,727 | 9,262 | 132,273 |
|
||||
| `json::parse` | 1,352 | 2,386 | 5,915 | 163,750 |
|
||||
|
||||
<div class="nj-fig-wrap" markdown>
|
||||
--8<-- "images/perf_blog_view.svg"
|
||||
</div>
|
||||
|
||||
On the same four files, reading every value takes yyjson 1.06 to 1.30 times as long as `json_document`, writing
|
||||
them back with `dump()` 1.06 to 1.35 times, and parsing, editing a few values and writing them 1.34 to 1.85 times (1.0 to 1.57 times for an edit in every
|
||||
record). Integers are
|
||||
already converted when you read them, and the writer copies strings and integer tokens straight from the source
|
||||
([#5633][5633]).
|
||||
The fastest *other* engine for each workload, as its time divided by `json_document`'s, over the four files above:
|
||||
above 1, `json_document` is ahead; below 1, it is behind.
|
||||
|
||||
It is not faster everywhere, and the harness ([#5627][5627], [#5914][5914]) is built to show where:
|
||||
| workload | M1 Max, Apple clang 21 | x86-64, GCC 13 | x86-64, Clang 18 |
|
||||
| --- | --- | --- | --- |
|
||||
| parse | 1.06–1.58 (yyjson, simdjson DOM) | 0.97–1.01 (simdjson DOM) on `twitter`, `citm_catalog`; 1.89 on `canada`; **0.71** (sonic-cpp) on `jeopardy` | 0.96–0.97 (simdjson DOM) on `twitter`, `citm_catalog`; 1.21–1.56 on `canada`, `jeopardy` |
|
||||
| traverse | 1.04–1.18 (yyjson, simdjson On-Demand) | **0.58–0.86** (simdjson On-Demand) | **0.86**–1.20 (sonic-cpp, simdjson On-Demand, yyjson) |
|
||||
| select | **0.34–0.84** (Glaze structs, simdjson On-Demand) | **0.26–0.65** | **0.33–0.86** |
|
||||
| parse+dump | 1.18–1.35 (yyjson) | 1.20–1.41 (yyjson, sonic-cpp) | 1.16–1.27 (yyjson, sonic-cpp) |
|
||||
|
||||
- **Reading a few fields.** simdjson's On-Demand API builds nothing and can only read forward. Picking a few fields
|
||||
out of `twitter.json`, `canada.json` and `jeopardy.json` takes it 0.67 to 0.80 times as long as `json_document`.
|
||||
- **Floats are converted later.** `json_document` converts a float when you read it; yyjson and simdjson convert
|
||||
every number while parsing. For `canada.json`, which is almost all floats, the parse row therefore flatters
|
||||
`json_document` (1.55× ahead of yyjson); reading every value after parsing is the fair comparison, and there it
|
||||
is 1.07× ahead.
|
||||
- **Other CPUs.** On the x86-64 machine with GCC, simdjson's DOM with AVX2 was 19 % ahead on parsing
|
||||
`twitter.json` and 7 % on `citm_catalog.json` ([#5627][5627]), and yyjson's `dump()` of `canada.json` still is
|
||||
ahead: `json_document` takes 1.4 times as long there ([#5908][5908]). Our tables are from one Apple silicon
|
||||
machine.
|
||||
- **Small documents.** For a 2.5 KB status message, all three engines parse in about a microsecond, and yyjson is
|
||||
6 % ahead. For a 94-byte message, the engines trade places between runs.
|
||||
- **`json::parse` itself.** Boost.JSON builds a mutable tree, as `json` does, so it is the fair comparison for
|
||||
`json::parse`, not for `json_document`. It is still 1.6 to 2.4 times as fast.
|
||||
So, is it the fastest JSON parser? Not in general. Among the parsers that build a document you can read in any
|
||||
order, it is the fastest at parsing and writing back in every configuration we ran, and the fastest at parsing on
|
||||
Apple silicon. On x86-64 it ties with simdjson's DOM on typical documents. Where it loses:
|
||||
|
||||
- **Reading a few known fields.** simdjson's On-Demand API builds nothing and reads forward only; Glaze reading into
|
||||
structs that declare just the needed fields skips everything else without building it. Both are faster for
|
||||
*select*, Glaze by up to 3.8× on `canada.json`, where it skips the coordinates.
|
||||
- **One pass over everything on x86-64 with GCC.** simdjson On-Demand visits every value in 0.58 to 0.86 of the time.
|
||||
- **Fresh large documents on Linux.** A fresh 56 MB `jeopardy.json` pays for the page faults of a new index of
|
||||
3.25 million 16-byte nodes (52 MB). With GCC, sonic-cpp parses it in 0.71 of the time. Reusing the document (`read()`) halves `json_document`'s time
|
||||
there, and then it is ahead of a reused simdjson parser (0.53 against 0.61 of the fresh time).
|
||||
- **Float-heavy documents, measured fairly.** `json_document` converts a float when you read it; the others convert
|
||||
while parsing. The `canada.json` parse row flatters it; *traverse* is the fair comparison, and there it is
|
||||
1.04× ahead on the Mac and behind sonic-cpp with Clang on x86-64 (0.88).
|
||||
- **Small documents.** On a 2.5 KB message, all document parsers take about a microsecond, and yyjson and
|
||||
simdjson's DOM are as fast or a few percent faster.
|
||||
|
||||
And `json::parse`? Boost.JSON builds a mutable tree as `json` does, so it is the fair comparison. It is 1.6 to 2.4
|
||||
times as fast on the Mac, and 2.4 to 4.5 times on the x86-64 server.
|
||||
|
||||
The programs are in
|
||||
[`tests/benchmarks/json_view/others`](https://github.com/nlohmann/json/tree/develop/tests/benchmarks/json_view/others),
|
||||
with the pinned versions and checksums of every library.
|
||||
|
||||
## What didn't work
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<svg class="nj-fig nj-charts nj-charts--blog" viewBox="0 0 580 404" role="img" aria-labelledby="nj-blog-view nj-blog-view-d" xmlns="http://www.w3.org/2000/svg">
|
||||
<title id="nj-blog-view">Parse throughput of json_document, yyjson, simdjson's D​OM, Boost.J​SON and json::parse, Apple M1 Max</title>
|
||||
<desc id="nj-blog-view-d">Grouped horizontal bars in GB/s. twitter.json json_document 3.48 GB/s; twitter.json yyjson 3.29 GB/s; twitter.json simdjson D​OM 2.92 GB/s; twitter.json Boost.J​SON 0.73 GB/s; twitter.json json::parse 0.46 GB/s; citm_catalog.json json_document 4.80 GB/s; citm_catalog.json yyjson 3.61 GB/s; citm_catalog.json simdjson D​OM 3.52 GB/s; citm_catalog.json Boost.J​SON 1.17 GB/s; citm_catalog.json json::parse 0.72 GB/s; canada.json json_document 2.35 GB/s; canada.json yyjson 1.51 GB/s; canada.json simdjson D​OM 1.07 GB/s; canada.json Boost.J​SON 0.90 GB/s; canada.json json::parse 0.38 GB/s; jeopardy.json json_document 2.45 GB/s; jeopardy.json yyjson 1.82 GB/s; jeopardy.json simdjson D​OM 2.07 GB/s; jeopardy.json Boost.J​SON 0.62 GB/s; jeopardy.json json::parse 0.33 GB/s.</desc>
|
||||
<svg class="nj-fig nj-charts nj-charts--blog" viewBox="0 0 580 472" role="img" aria-labelledby="nj-blog-view nj-blog-view-d" xmlns="http://www.w3.org/2000/svg">
|
||||
<title id="nj-blog-view">Parse throughput of json_document and six other document parsers, fresh documents, Apple M1 Max</title>
|
||||
<desc id="nj-blog-view-d">Grouped horizontal bars in GB/s. twitter.json json_document 3.45 GB/s; twitter.json yyjson 3.26 GB/s; twitter.json simdjson D​OM 3.13 GB/s; twitter.json sonic-rs (Rust) 2.09 GB/s; twitter.json sonic-cpp 1.67 GB/s; twitter.json Boost.J​SON 0.73 GB/s; twitter.json json::parse 0.47 GB/s; citm_catalog.json json_document 4.75 GB/s; citm_catalog.json yyjson 3.61 GB/s; citm_catalog.json simdjson D​OM 3.55 GB/s; citm_catalog.json sonic-rs (Rust) 2.60 GB/s; citm_catalog.json sonic-cpp 1.75 GB/s; citm_catalog.json Boost.J​SON 1.16 GB/s; citm_catalog.json json::parse 0.72 GB/s; canada.json json_document 2.39 GB/s; canada.json yyjson 1.51 GB/s; canada.json simdjson D​OM 1.07 GB/s; canada.json sonic-rs (Rust) 1.18 GB/s; canada.json sonic-cpp 0.87 GB/s; canada.json Boost.J​SON 0.91 GB/s; canada.json json::parse 0.38 GB/s; jeopardy.json json_document 2.45 GB/s; jeopardy.json yyjson 1.83 GB/s; jeopardy.json simdjson D​OM 2.06 GB/s; jeopardy.json sonic-rs (Rust) 1.84 GB/s; jeopardy.json sonic-cpp 1.36 GB/s; jeopardy.json Boost.J​SON 0.62 GB/s; jeopardy.json json::parse 0.34 GB/s.</desc>
|
||||
<rect class="nj-charts-c1" x="8" y="10" width="12" height="12" rx="3"/>
|
||||
<text class="nj-charts-leg" x="26" y="20.5">json_document</text>
|
||||
<rect class="nj-charts-c2" x="138.2" y="10" width="12" height="12" rx="3"/>
|
||||
@@ -8,73 +8,93 @@
|
||||
<rect class="nj-charts-c3" x="216.6" y="10" width="12" height="12" rx="3"/>
|
||||
<text class="nj-charts-leg" x="234.6" y="20.5">simdjson D​OM</text>
|
||||
<rect class="nj-charts-c4" x="339.4" y="10" width="12" height="12" rx="3"/>
|
||||
<text class="nj-charts-leg" x="357.4" y="20.5">Boost.J​SON</text>
|
||||
<rect class="nj-charts-c5" x="447.4" y="10" width="12" height="12" rx="3"/>
|
||||
<text class="nj-charts-leg" x="465.4" y="20.5">json::parse</text>
|
||||
<line class="nj-charts-grid" x1="182.3" y1="40" x2="182.3" y2="360"/>
|
||||
<text class="nj-charts-tick" x="182.3" y="376">0.5</text>
|
||||
<line class="nj-charts-grid" x1="222.6" y1="40" x2="222.6" y2="360"/>
|
||||
<text class="nj-charts-tick" x="222.6" y="376">1</text>
|
||||
<line class="nj-charts-grid" x1="262.9" y1="40" x2="262.9" y2="360"/>
|
||||
<text class="nj-charts-tick" x="262.9" y="376">1.5</text>
|
||||
<line class="nj-charts-grid" x1="303.2" y1="40" x2="303.2" y2="360"/>
|
||||
<text class="nj-charts-tick" x="303.2" y="376">2</text>
|
||||
<line class="nj-charts-grid" x1="343.5" y1="40" x2="343.5" y2="360"/>
|
||||
<text class="nj-charts-tick" x="343.5" y="376">2.5</text>
|
||||
<line class="nj-charts-grid" x1="383.8" y1="40" x2="383.8" y2="360"/>
|
||||
<text class="nj-charts-tick" x="383.8" y="376">3</text>
|
||||
<line class="nj-charts-grid" x1="424.1" y1="40" x2="424.1" y2="360"/>
|
||||
<text class="nj-charts-tick" x="424.1" y="376">3.5</text>
|
||||
<line class="nj-charts-grid" x1="464.4" y1="40" x2="464.4" y2="360"/>
|
||||
<text class="nj-charts-tick" x="464.4" y="376">4</text>
|
||||
<line class="nj-charts-grid" x1="504.7" y1="40" x2="504.7" y2="360"/>
|
||||
<text class="nj-charts-tick" x="504.7" y="376">4.5</text>
|
||||
<line class="nj-charts-grid" x1="545" y1="40" x2="545" y2="360"/>
|
||||
<text class="nj-charts-tick" x="545" y="376">5</text>
|
||||
<text class="nj-charts-tick" x="343.5" y="394">GB/s, longer is faster</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="83.5" text-anchor="end">twitter.json</text>
|
||||
<path class="nj-charts-c1" d="M142 44 H418.132 Q422.132 44 422.132 48 V51 Q422.132 55 418.132 55 H142 Z"><title>json_document, twitter.json: 3.48 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="426.132" y="53.5">3.48</text>
|
||||
<path class="nj-charts-c2" d="M142 57 H403.104 Q407.104 57 407.104 61 V64 Q407.104 68 403.104 68 H142 Z"><title>yyjson, twitter.json: 3.29 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="411.104" y="66.5">3.29</text>
|
||||
<path class="nj-charts-c3" d="M142 70 H373.213 Q377.213 70 377.213 74 V77 Q377.213 81 373.213 81 H142 Z"><title>simdjson D​OM, twitter.json: 2.92 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="381.213" y="79.5">2.92</text>
|
||||
<path class="nj-charts-c4" d="M142 83 H196.776 Q200.776 83 200.776 87 V90 Q200.776 94 196.776 94 H142 Z"><title>Boost.J​SON, twitter.json: 0.73 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="204.776" y="92.5">0.73</text>
|
||||
<path class="nj-charts-c5" d="M142 96 H175.208 Q179.208 96 179.208 100 V103 Q179.208 107 175.208 107 H142 Z"><title>json::parse, twitter.json: 0.46 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="183.208" y="105.5">0.46</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="162.5" text-anchor="end">citm_catalog.json</text>
|
||||
<path class="nj-charts-c1" d="M142 123 H524.809 Q528.809 123 528.809 127 V130 Q528.809 134 524.809 134 H142 Z"><title>json_document, citm_catalog.json: 4.80 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="532.809" y="132.5">4.80</text>
|
||||
<path class="nj-charts-c2" d="M142 136 H429.179 Q433.179 136 433.179 140 V143 Q433.179 147 429.179 147 H142 Z"><title>yyjson, citm_catalog.json: 3.61 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="437.179" y="145.5">3.61</text>
|
||||
<path class="nj-charts-c3" d="M142 149 H421.992 Q425.992 149 425.992 153 V156 Q425.992 160 421.992 160 H142 Z"><title>simdjson D​OM, citm_catalog.json: 3.52 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="429.992" y="158.5">3.52</text>
|
||||
<path class="nj-charts-c4" d="M142 162 H232.063 Q236.063 162 236.063 166 V169 Q236.063 173 232.063 173 H142 Z"><title>Boost.J​SON, citm_catalog.json: 1.17 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="240.063" y="171.5">1.17</text>
|
||||
<path class="nj-charts-c5" d="M142 175 H195.789 Q199.789 175 199.789 179 V182 Q199.789 186 195.789 186 H142 Z"><title>json::parse, citm_catalog.json: 0.72 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="203.789" y="184.5">0.72</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="241.5" text-anchor="end">canada.json</text>
|
||||
<path class="nj-charts-c1" d="M142 202 H327.093 Q331.093 202 331.093 206 V209 Q331.093 213 327.093 213 H142 Z"><title>json_document, canada.json: 2.35 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="335.093" y="211.5">2.35</text>
|
||||
<path class="nj-charts-c2" d="M142 215 H259.85 Q263.85 215 263.85 219 V222 Q263.85 226 259.85 226 H142 Z"><title>yyjson, canada.json: 1.51 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="267.85" y="224.5">1.51</text>
|
||||
<path class="nj-charts-c3" d="M142 228 H224.48 Q228.48 228 228.48 232 V235 Q228.48 239 224.48 239 H142 Z"><title>simdjson D​OM, canada.json: 1.07 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="232.48" y="237.5">1.07</text>
|
||||
<path class="nj-charts-c4" d="M142 241 H210.545 Q214.545 241 214.545 245 V248 Q214.545 252 210.545 252 H142 Z"><title>Boost.J​SON, canada.json: 0.90 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="218.545" y="250.5">0.90</text>
|
||||
<path class="nj-charts-c5" d="M142 254 H168.804 Q172.804 254 172.804 258 V261 Q172.804 265 168.804 265 H142 Z"><title>json::parse, canada.json: 0.38 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="176.804" y="263.5">0.38</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="320.5" text-anchor="end">jeopardy.json</text>
|
||||
<path class="nj-charts-c1" d="M142 281 H335.369 Q339.369 281 339.369 285 V288 Q339.369 292 335.369 292 H142 Z"><title>json_document, jeopardy.json: 2.45 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="343.369" y="290.5">2.45</text>
|
||||
<path class="nj-charts-c2" d="M142 294 H284.675 Q288.675 294 288.675 298 V301 Q288.675 305 284.675 305 H142 Z"><title>yyjson, jeopardy.json: 1.82 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="292.675" y="303.5">1.82</text>
|
||||
<path class="nj-charts-c3" d="M142 307 H304.612 Q308.612 307 308.612 311 V314 Q308.612 318 304.612 318 H142 Z"><title>simdjson D​OM, jeopardy.json: 2.07 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="312.612" y="316.5">2.07</text>
|
||||
<path class="nj-charts-c4" d="M142 320 H188.368 Q192.368 320 192.368 324 V327 Q192.368 331 188.368 331 H142 Z"><title>Boost.J​SON, jeopardy.json: 0.62 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="196.368" y="329.5">0.62</text>
|
||||
<path class="nj-charts-c5" d="M142 333 H164.706 Q168.706 333 168.706 337 V340 Q168.706 344 164.706 344 H142 Z"><title>json::parse, jeopardy.json: 0.33 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="172.706" y="342.5">0.33</text>
|
||||
<line class="nj-charts-zero" x1="142" y1="40" x2="142" y2="360"/>
|
||||
<text class="nj-charts-leg" x="357.4" y="20.5">sonic-rs (Rust)</text>
|
||||
<rect class="nj-charts-c5" x="8" y="30" width="12" height="12" rx="3"/>
|
||||
<text class="nj-charts-leg" x="26" y="40.5">sonic-cpp</text>
|
||||
<rect class="nj-charts-c6" x="108.6" y="30" width="12" height="12" rx="3"/>
|
||||
<text class="nj-charts-leg" x="126.6" y="40.5">Boost.J​SON</text>
|
||||
<rect class="nj-charts-c1 nj-charts-dim" x="216.6" y="30" width="12" height="12" rx="3"/>
|
||||
<text class="nj-charts-leg" x="234.6" y="40.5">json::parse</text>
|
||||
<line class="nj-charts-grid" x1="182.3" y1="60" x2="182.3" y2="428"/>
|
||||
<text class="nj-charts-tick" x="182.3" y="444">0.5</text>
|
||||
<line class="nj-charts-grid" x1="222.6" y1="60" x2="222.6" y2="428"/>
|
||||
<text class="nj-charts-tick" x="222.6" y="444">1</text>
|
||||
<line class="nj-charts-grid" x1="262.9" y1="60" x2="262.9" y2="428"/>
|
||||
<text class="nj-charts-tick" x="262.9" y="444">1.5</text>
|
||||
<line class="nj-charts-grid" x1="303.2" y1="60" x2="303.2" y2="428"/>
|
||||
<text class="nj-charts-tick" x="303.2" y="444">2</text>
|
||||
<line class="nj-charts-grid" x1="343.5" y1="60" x2="343.5" y2="428"/>
|
||||
<text class="nj-charts-tick" x="343.5" y="444">2.5</text>
|
||||
<line class="nj-charts-grid" x1="383.8" y1="60" x2="383.8" y2="428"/>
|
||||
<text class="nj-charts-tick" x="383.8" y="444">3</text>
|
||||
<line class="nj-charts-grid" x1="424.1" y1="60" x2="424.1" y2="428"/>
|
||||
<text class="nj-charts-tick" x="424.1" y="444">3.5</text>
|
||||
<line class="nj-charts-grid" x1="464.4" y1="60" x2="464.4" y2="428"/>
|
||||
<text class="nj-charts-tick" x="464.4" y="444">4</text>
|
||||
<line class="nj-charts-grid" x1="504.7" y1="60" x2="504.7" y2="428"/>
|
||||
<text class="nj-charts-tick" x="504.7" y="444">4.5</text>
|
||||
<line class="nj-charts-grid" x1="545" y1="60" x2="545" y2="428"/>
|
||||
<text class="nj-charts-tick" x="545" y="444">5</text>
|
||||
<text class="nj-charts-tick" x="343.5" y="462">GB/s, longer is faster</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="109.5" text-anchor="end">twitter.json</text>
|
||||
<path class="nj-charts-c1" d="M142 64 H416.142 Q420.142 64 420.142 68 V69 Q420.142 73 416.142 73 H142 Z"><title>json_document, twitter.json: 3.45 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="424.142" y="71.5">3.45</text>
|
||||
<path class="nj-charts-c2" d="M142 75 H400.371 Q404.371 75 404.371 79 V80 Q404.371 84 400.371 84 H142 Z"><title>yyjson, twitter.json: 3.26 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="408.371" y="82.5">3.26</text>
|
||||
<path class="nj-charts-c3" d="M142 86 H389.98 Q393.98 86 393.98 90 V91 Q393.98 95 389.98 95 H142 Z"><title>simdjson D​OM, twitter.json: 3.13 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="397.98" y="93.5">3.13</text>
|
||||
<path class="nj-charts-c4" d="M142 97 H306.543 Q310.543 97 310.543 101 V102 Q310.543 106 306.543 106 H142 Z"><title>sonic-rs (Rust), twitter.json: 2.09 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="314.543" y="104.5">2.09</text>
|
||||
<path class="nj-charts-c5" d="M142 108 H272.301 Q276.301 108 276.301 112 V113 Q276.301 117 272.301 117 H142 Z"><title>sonic-cpp, twitter.json: 1.67 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="280.301" y="115.5">1.67</text>
|
||||
<path class="nj-charts-c6" d="M142 119 H196.641 Q200.641 119 200.641 123 V124 Q200.641 128 196.641 128 H142 Z"><title>Boost.J​SON, twitter.json: 0.73 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="204.641" y="126.5">0.73</text>
|
||||
<path class="nj-charts-c1 nj-charts-dim" d="M142 130 H175.648 Q179.648 130 179.648 134 V135 Q179.648 139 175.648 139 H142 Z"><title>json::parse, twitter.json: 0.47 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="183.648" y="137.5">0.47</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="200.5" text-anchor="end">citm_catalog.json</text>
|
||||
<path class="nj-charts-c1" d="M142 155 H520.452 Q524.452 155 524.452 159 V160 Q524.452 164 520.452 164 H142 Z"><title>json_document, citm_catalog.json: 4.75 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="528.452" y="162.5">4.75</text>
|
||||
<path class="nj-charts-c2" d="M142 166 H429.24 Q433.24 166 433.24 170 V171 Q433.24 175 429.24 175 H142 Z"><title>yyjson, citm_catalog.json: 3.61 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="437.24" y="173.5">3.61</text>
|
||||
<path class="nj-charts-c3" d="M142 177 H424.446 Q428.446 177 428.446 181 V182 Q428.446 186 424.446 186 H142 Z"><title>simdjson D​OM, citm_catalog.json: 3.55 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="432.446" y="184.5">3.55</text>
|
||||
<path class="nj-charts-c4" d="M142 188 H347.658 Q351.658 188 351.658 192 V193 Q351.658 197 347.658 197 H142 Z"><title>sonic-rs (Rust), citm_catalog.json: 2.60 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="355.658" y="195.5">2.60</text>
|
||||
<path class="nj-charts-c5" d="M142 199 H279.189 Q283.189 199 283.189 203 V204 Q283.189 208 279.189 208 H142 Z"><title>sonic-cpp, citm_catalog.json: 1.75 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="287.189" y="206.5">1.75</text>
|
||||
<path class="nj-charts-c6" d="M142 210 H231.872 Q235.872 210 235.872 214 V215 Q235.872 219 231.872 219 H142 Z"><title>Boost.J​SON, citm_catalog.json: 1.16 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="239.872" y="217.5">1.16</text>
|
||||
<path class="nj-charts-c1 nj-charts-dim" d="M142 221 H196.346 Q200.346 221 200.346 225 V226 Q200.346 230 196.346 230 H142 Z"><title>json::parse, citm_catalog.json: 0.72 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="204.346" y="228.5">0.72</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="291.5" text-anchor="end">canada.json</text>
|
||||
<path class="nj-charts-c1" d="M142 246 H330.402 Q334.402 246 334.402 250 V251 Q334.402 255 330.402 255 H142 Z"><title>json_document, canada.json: 2.39 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="338.402" y="253.5">2.39</text>
|
||||
<path class="nj-charts-c2" d="M142 257 H259.85 Q263.85 257 263.85 261 V262 Q263.85 266 259.85 266 H142 Z"><title>yyjson, canada.json: 1.51 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="267.85" y="264.5">1.51</text>
|
||||
<path class="nj-charts-c3" d="M142 268 H224.521 Q228.521 268 228.521 272 V273 Q228.521 277 224.521 277 H142 Z"><title>simdjson D​OM, canada.json: 1.07 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="232.521" y="275.5">1.07</text>
|
||||
<path class="nj-charts-c4" d="M142 279 H233.141 Q237.141 279 237.141 283 V284 Q237.141 288 233.141 288 H142 Z"><title>sonic-rs (Rust), canada.json: 1.18 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="241.141" y="286.5">1.18</text>
|
||||
<path class="nj-charts-c5" d="M142 290 H208.324 Q212.324 290 212.324 294 V295 Q212.324 299 208.324 299 H142 Z"><title>sonic-cpp, canada.json: 0.87 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="216.324" y="297.5">0.87</text>
|
||||
<path class="nj-charts-c6" d="M142 301 H211.13 Q215.13 301 215.13 305 V306 Q215.13 310 211.13 310 H142 Z"><title>Boost.J​SON, canada.json: 0.91 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="219.13" y="308.5">0.91</text>
|
||||
<path class="nj-charts-c1 nj-charts-dim" d="M142 312 H168.674 Q172.674 312 172.674 316 V317 Q172.674 321 168.674 321 H142 Z"><title>json::parse, canada.json: 0.38 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="176.674" y="319.5">0.38</text>
|
||||
<text class="nj-charts-rowlabel" x="134" y="382.5" text-anchor="end">jeopardy.json</text>
|
||||
<path class="nj-charts-c1" d="M142 337 H335.421 Q339.421 337 339.421 341 V342 Q339.421 346 335.421 346 H142 Z"><title>json_document, jeopardy.json: 2.45 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="343.421" y="344.5">2.45</text>
|
||||
<path class="nj-charts-c2" d="M142 348 H285.574 Q289.574 348 289.574 352 V353 Q289.574 357 285.574 357 H142 Z"><title>yyjson, jeopardy.json: 1.83 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="293.574" y="355.5">1.83</text>
|
||||
<path class="nj-charts-c3" d="M142 359 H304.433 Q308.433 359 308.433 363 V364 Q308.433 368 304.433 368 H142 Z"><title>simdjson D​OM, jeopardy.json: 2.06 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="312.433" y="366.5">2.06</text>
|
||||
<path class="nj-charts-c4" d="M142 370 H286.258 Q290.258 370 290.258 374 V375 Q290.258 379 286.258 379 H142 Z"><title>sonic-rs (Rust), jeopardy.json: 1.84 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="294.258" y="377.5">1.84</text>
|
||||
<path class="nj-charts-c5" d="M142 381 H247.737 Q251.737 381 251.737 385 V386 Q251.737 390 247.737 390 H142 Z"><title>sonic-cpp, jeopardy.json: 1.36 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="255.737" y="388.5">1.36</text>
|
||||
<path class="nj-charts-c6" d="M142 392 H188.354 Q192.354 392 192.354 396 V397 Q192.354 401 188.354 401 H142 Z"><title>Boost.J​SON, jeopardy.json: 0.62 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="196.354" y="399.5">0.62</text>
|
||||
<path class="nj-charts-c1 nj-charts-dim" d="M142 403 H165.345 Q169.345 403 169.345 407 V408 Q169.345 412 165.345 412 H142 Z"><title>json::parse, jeopardy.json: 0.34 GB/s</title></path>
|
||||
<text class="nj-charts-val" x="173.345" y="410.5">0.34</text>
|
||||
<line class="nj-charts-zero" x1="142" y1="60" x2="142" y2="428"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 11 KiB |
@@ -7,7 +7,7 @@ Generated files:
|
||||
json.hpp or json_view.hpp since 3.12.0, one panel each
|
||||
- perf_blog_swar.svg: the eight-byte string test on one word of input
|
||||
- perf_blog_cliffs.svg: operations that were quadratic or worse, 3.12.0 against 3.13.0 (log scale)
|
||||
- perf_blog_view.svg: parse throughput of json_document, yyjson, simdjson's DOM, Boost.JSON and json::parse
|
||||
- perf_blog_view.svg: parse throughput of json_document and six other document parsers
|
||||
|
||||
The numbers are copied from the tables of the post (the timeline from data/perf_timeline.csv, which
|
||||
`tests/benchmarks/history/history.py summarize` writes); the tables stay on the page as the accessible fallback. Update both together.
|
||||
@@ -303,12 +303,14 @@ def cliffs():
|
||||
# engines and GB/s per file, copied from the table in "Build a different data structure"
|
||||
VIEW_FILES = ["twitter.json", "citm_catalog.json", "canada.json", "jeopardy.json"]
|
||||
VIEW_BYTES = [631514, 1727204, 2251051, 55554625]
|
||||
VIEW_US = [ # (engine, css class, [µs per file])
|
||||
("json_document", "nj-charts-c1", [181.7, 359.9, 959.5, 22687]),
|
||||
("yyjson", "nj-charts-c2", [192.0, 478.1, 1489, 30528]),
|
||||
("simdjson DOM", "nj-charts-c3", [216.4, 490.2, 2098, 26875]),
|
||||
("Boost.JSON", "nj-charts-c4", [866.0, 1480, 2501, 88900]),
|
||||
("json::parse", "nj-charts-c5", [1368, 2409, 5890, 167664]),
|
||||
VIEW_US = [ # (engine, css class, [µs per file]), fresh documents, from the table in "How it compares"
|
||||
("json_document", "nj-charts-c1", [183, 364, 943, 22681]),
|
||||
("yyjson", "nj-charts-c2", [194, 478, 1489, 30342]),
|
||||
("simdjson DOM", "nj-charts-c3", [202, 486, 2097, 26904]),
|
||||
("sonic-rs (Rust)", "nj-charts-c4", [302, 664, 1907, 30202]),
|
||||
("sonic-cpp", "nj-charts-c5", [379, 986, 2580, 40804]),
|
||||
("Boost.JSON", "nj-charts-c6", [868, 1483, 2481, 88925]),
|
||||
("json::parse", "nj-charts-c1 nj-charts-dim", [1352, 2386, 5915, 163750]),
|
||||
]
|
||||
VIEW = [(e, c, [n / (t * 1000) for n, t in zip(VIEW_BYTES, us)]) for e, c, us in VIEW_US] # GB/s
|
||||
|
||||
@@ -318,15 +320,18 @@ def view():
|
||||
hi = max(max(v) for _, _, v in VIEW)
|
||||
hi = math.ceil(hi * 2) / 2
|
||||
X = lambda v: L + v / hi * (R - L)
|
||||
bh, gap = 11, 2
|
||||
top = 44
|
||||
bh, gap = 9, 2
|
||||
top = 64
|
||||
group_h = len(VIEW) * (bh + gap) + 14
|
||||
b, desc = [], []
|
||||
x = 8
|
||||
x, ly = 8, 10
|
||||
for j, (eng, cls, _) in enumerate(VIEW):
|
||||
b.append('<rect class="%s" x="%g" y="10" width="12" height="12" rx="3"/>' % (cls, x))
|
||||
b.append('<text class="nj-charts-leg" x="%g" y="20.5">%s</text>' % (x + 18, esc(eng)))
|
||||
x += 18 + 7.4 * len(eng) + 16
|
||||
w = 18 + 7.4 * len(eng) + 16
|
||||
if x + w > W:
|
||||
x, ly = 8, ly + 20
|
||||
b.append('<rect class="%s" x="%g" y="%g" width="12" height="12" rx="3"/>' % (cls, x, ly))
|
||||
b.append('<text class="nj-charts-leg" x="%g" y="%g">%s</text>' % (x + 18, ly + 10.5, esc(eng)))
|
||||
x += w
|
||||
axis_y = top + group_h * len(VIEW_FILES)
|
||||
t = 0.5
|
||||
while t <= hi + 1e-9:
|
||||
@@ -344,7 +349,7 @@ def view():
|
||||
desc.append("%s %s %.2f GB/s" % (f, eng, vals[i]))
|
||||
b.append('<line class="nj-charts-zero" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(0), top - 4, X(0), axis_y))
|
||||
write("perf_blog_view.svg", W, axis_y + 44, "nj-charts--blog", "nj-blog-view",
|
||||
"Parse throughput of json_document, yyjson, simdjson's DOM, Boost.JSON and json::parse, Apple M1 Max",
|
||||
"Parse throughput of json_document and six other document parsers, fresh documents, Apple M1 Max",
|
||||
"Grouped horizontal bars in GB/s. " + "; ".join(desc) + ".", b)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user