docs: add the blog post "How 3.13.0 got faster"

A post for the documentation (Home > Blog) on how 3.13.0 became faster:
eight themes with the pull requests behind them, the ideas taken from other
libraries, what did not work, how the fast paths are tested, and the
compile-time cost. Every number comes from a run on 2026-10-27 (3.12.0 against
develop plus the open non-draft PRs, Apple M1 Max) or from the linked PR.

- docs/mkdocs/docs/home/blog/how_3_13_0_got_faster.md: the post.
- docs/mkdocs/scripts/figures/perf_blog.py: draws its 12 figures (overview,
  eight timeline panels, the SWAR test, the cliffs, json_view throughput) as
  inline SVGs in the nj-charts style; data/perf_timeline.csv holds the
  timeline.
- tests/benchmarks/history: history.cpp and history.py time one fixed program
  against the header of every commit that changed it, interleaved, and write
  one CSV row per commit with its PR. The timeline of the post comes from it.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-30 15:29:45 +01:00
1 parent d20c4dcd89
commit ea848cd2e8
21 files changed
+2297

No files matched your search

+4
View File
@@ -27,6 +27,10 @@
.md-typeset svg.nj-charts--compile, .md-typeset svg.nj-charts--scaling { max-width: 26rem; } .md-typeset svg.nj-charts--compile, .md-typeset svg.nj-charts--scaling { max-width: 26rem; }
.md-typeset svg.nj-charts--sizes { max-width: 26rem; } .md-typeset svg.nj-charts--sizes { max-width: 26rem; }
/* home/blog/how_3_13_0_got_faster.md (scripts/figures/perf_blog.py) */
.md-typeset svg.nj-charts--blog { max-width: 34rem; }
.md-typeset svg.nj-charts--swar { max-width: 34rem; }
.md-typeset svg.nj-charts--timeline { max-width: 22rem; }
.nj-charts text { fill: currentColor; font-size: 13px; } .nj-charts text { fill: currentColor; font-size: 13px; }
.nj-charts .nj-charts-leg { font-size: 13.5px; } .nj-charts .nj-charts-leg { font-size: 13.5px; }
@@ -0,0 +1,774 @@
# How nlohmann/json 3.13.0 got 2.9× faster
Since 2016, the README of this library has said this about speed:
> There are certainly faster JSON libraries out there. However, if your goal is to speed up your development by adding
> JSON support with a single header, then this library is the way to go.
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).
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
worth writing about is the combination, and the conditions it had to work under: a C++11 header-only library with a
value type that is a template over its string, number, object and allocator types, input from strings, streams,
`FILE*`, iterator pairs, wide strings and user-defined adapters, output that had to stay byte-for-byte the same (with one deliberate exception, see theme 3), and error messages that had to keep pointing at the same byte.
We tried to be careful about what we claim. Every number below comes either from a benchmark we ran for this post
(described in [How we measured](#how-we-measured)) or from the description of the pull request that made the change,
which we link. The PR numbers were measured at the time against the state before the PR, often on more than one
machine, and say so.
## The short version
Apple M1 Max, Apple clang 21, `-O3 -flto`, the compiler's default standard (C++14); the same benchmark source for both
headers. The parse rows do not include destroying the result (the suite pauses the timer for that):
| workload | 3.12.0 | 3.13.0 | speedup |
| --- | --: | --: | --: |
| `json::parse()` of `twitter.json` | 3.16 ms | 1.05 ms | 3.0× |
| `json::parse()` of `citm_catalog.json` | 7.20 ms | 1.75 ms | 4.1× |
| `json::parse()` of `canada.json` | 15.1 ms | 4.35 ms | 3.5× |
| `json::parse()` of `canada.json`, indented by 4 spaces | 33.8 ms | 5.02 ms | 6.7× |
| `ordered_json::parse()` of `citm_catalog.json` | 10.8 ms | 1.64 ms | 6.6× |
| `json::parse()` of `twitter.json` from an `std::ifstream` | 3.34 ms | 1.35 ms | 2.5× |
| `json::parse()` of `citm_catalog.json` from a `FILE*` | 34.6 ms | 7.26 ms | 4.8× |
| `json::accept()` of `citm_catalog.json` | 6.36 ms | 0.91 ms | 7.0× |
| `dump()` of `twitter.json` | 1.39 ms | 0.208 ms | 6.7× |
| `dump()` of `canada.json` | 6.63 ms | 2.25 ms | 2.9× |
| `dump(4)` of `citm_catalog.json` | 1.93 ms | 0.416 ms | 4.6× |
| `to_cbor()` of `twitter.json` | 0.638 ms | 0.142 ms | 4.5× |
| `from_cbor()` of `twitter.json` from memory | 3.00 ms | 0.965 ms | 3.1× |
| `from_cbor()` of `twitter.json` from a `FILE*` | 9.71 ms | 1.54 ms | 6.3× |
| `diff()` of `canada.json` with every eighth scalar changed | 38.3 ms | 3.67 ms | 10.4× |
| iterating over every value of `canada.json` | 0.861 ms | 0.320 ms | 2.7× |
| copying `citm_catalog.json` and destroying the copy | 1.61 ms | 1.45 ms | 1.11× |
| `==` of `citm_catalog.json` and a copy | 0.264 ms | 0.254 ms | 1.04× |
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_overview.svg"
</div>
The average over all 182 benchmarks of the suite is 2.93× (geometric mean); none got slower except the time of a
copy alone, 0.94 to 1.03× (copying and destroying together is 1.09 to 1.29× as fast). We have not measured where the
copy's few percent go; one known cost is the counter that bounds its recursion, about ten nanoseconds per copied
container in [#5389][5389]'s measurement. Copying and comparing gained the least.
One thing to keep in mind about `citm_catalog.json`: as distributed, it is indented, and 71 % of its 1.7 MB are
whitespace. Several changes below help exactly that. A minified copy of it parses 1.9× as fast as with 3.12.0 in our
timeline, against 3.3× for the file as distributed.
Eight themes did most of the work:
1. [Ask the input what it is](#1-ask-the-input-what-it-is), instead of reading every source one character at a time.
2. [Work on words, not bytes](#2-work-on-words-not-bytes): 8 bytes per step with plain integer arithmetic, 16 with
SSE2 on x86-64 and NEON on 64-bit Arm.
3. [Own the number conversions](#3-own-the-number-conversions): no `strtod`, no locale, no `snprintf`.
4. [Don't do work nobody reads](#4-dont-do-work-nobody-reads): positions, copies and conversions that only matter on
an error or for a rare caller.
5. [Read the assembly](#5-read-the-assembly): stack canaries, missed inlining and failed store forwarding.
6. [Write through a cursor](#6-write-through-a-cursor): no virtual call per character, no allocation per call, no
branch per integer.
7. [Fix the algorithm first](#7-fix-the-algorithm-first): seven operations were quadratic or worse.
8. [Build a different data structure](#8-build-a-different-data-structure) when you only want to read.
## Where the time went: a timeline
The suite compares two points. To see which change did what, we compiled one small benchmark against the header of
every commit on `develop` that changed `json.hpp` or `json_view.hpp` since 3.12.0, 315 of them, and ran all of them interleaved
(details in [How we measured](#how-we-measured)). Each panel shows the speedup over 3.12.0 after each commit; the
labels name the pull requests behind the largest steps. Each point is one build, and moving code around changes a
build's speed by a few percent on its own, so only the larger steps mean something. When `accept()` of
`twitter.json` got 2.5 % slower over the last 20 commits, we timed the two ends against each other in one binary
with six code layouts: they were equal within 0.2 %.
<div class="nj-charts-grid-wrap" markdown>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_parse_citm.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_parse_canada.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_accept_twitter.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_parse_twitter_ifstream.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_dump_twitter.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_dump_canada.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_from_cbor_twitter.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_timeline_to_cbor_twitter.svg"
</div>
</div>
A few things stand out:
- **There is no single big step.** Parsing `citm_catalog.json` got faster in about a dozen visible steps; the largest
are a buffer that only error messages read ([#5234][5234], −35 %), the contiguous-input fast paths
([#5283][5283], −20 %), and two consecutive PRs that each took 12 %: positions derived only on error
([#5809][5809]) and skipping indentation eight bytes at a time ([#5810][5810]). Most other PRs each moved it by 2
to 7 %.
- **Writing had a few large steps.** `dump()` of `twitter.json` lost 70 % of its time in one PR ([#5285][5285]: the
write buffer and the bulk string copy), and `dump()` of `canada.json` 65 % in another ([#5634][5634]: Żmij).
- **Some steps come from outside.** Two of the larger ones were contributed: [#5592][5592] by
[@mvanslobbe](https://github.com/mvanslobbe) checks for the expected `:` or `,` before the lexer's token switch
(−7 % on `citm_catalog.json`), and [#5328][5328] by [@alexprabhat99](https://github.com/alexprabhat99) stopped
creating a temporary `basic_json` for every object key that `to_cbor()` writes (−55 %).
- **Regressions happen in between.** [#5185][5185] added UTF-8 validation of every text string to the binary
readers, byte by byte. `from_cbor()` of `twitter.json` then took 37 % longer for 66 commits, until
[#5746][5746] (with [#5741][5741]) made the readers lenient again by default, as in 3.12.0, and the check an
option. That decision was about the format specifications, which don't require a decoder to check, not about
speed; the cost went with it. It never shipped in a release.
- **The parse panels include destroying the result.** The benchmark returns `json::parse(text).size()`, so the
destructor PRs ([#5762][5762], [#5835][5835]) show up in the parse panels too, as steps of up to 6 % in either
direction.
- **The input decides how big a step is.** #5234 measured 8 % on its own benchmark; on the indented
`citm_catalog.json` the same change saved 35 %, because every space went through the buffer it removed.
## 1. Ask the input what it is
This is the function the 3.12.0 lexer called for **every** byte of input:
```cpp
char_int_type get()
{
++position.chars_read_total;
++position.chars_read_current_line;
if (next_unget)
{
// just reset the next_unget variable and work with current
next_unget = false;
}
else
{
current = ia.get_character();
}
if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
{
token_string.push_back(char_traits<char_type>::to_char_type(current));
}
if (current == '\n')
{
++position.lines_read;
position.chars_read_current_line = 0;
}
return current;
}
```
Two counters in memory, a branch for a pending `unget()`, a call into the input adapter, a `push_back()` into a
buffer that only an error message reads, and a branch for line breaks. A string or a number then copied each byte a
second time into the token buffer. That is a clean design: one interface works for a `std::string`, an `std::istream`,
a `FILE*`, a pair of iterators over a `std::list<char>`, or a user's own adapter. But it makes every input pay for the
most limited one.
3.13.0 asks the input what it can do and picks a path at compile time:
```mermaid
flowchart LR
src[/"input"/] --> q{{"what is it?"}}
q -->|"std::string, std::vector,<br>pointers, contiguous ranges"| c["contiguous:<br>scan the whole buffer"]
q -->|"std::istream"| w["window:<br>scan the streambuf's get area"]
q -->|"FILE*"| f["one lock per parse,<br>unlocked reads"]
q -->|"other iterators,<br>user adapters"| b["byte at a time,<br>as before"]
```
<p class="nj-caption" markdown>The four kinds of input the lexer distinguishes in 3.13.0. Everything on the fast paths falls back to the byte path on anything unusual, so the result and the error messages stay the same.</p>
**Contiguous input** ([#5283][5283]). `std::string`, `std::vector<char>` and the like now go through a pointer-based
adapter in every C++ standard, not only C++20. On top of that, strings, numbers and runs of whitespace are scanned in
bulk (themes 2 and 3). Every fast path defers to the byte path on anything malformed, so error messages and `byte`
positions stay the same, with one deliberate correction (the column after a number at the end of a line); the PR
checked that on 481,000 documents.
**Positions only when someone asks** ([#5809][5809]). For seekable input, the lexer no longer counts lines and
columns while it reads. The byte offset is the distance from the start; lines and columns are recomputed from the
consumed input when an error message needs them. This is what serde_json's slice reader does. On an M1 Max, it made
parsing `citm_catalog.json` 11.8 % faster and validating an indented `twitter.json` 22 % faster.
**Streams** ([#5828][5828], [#5884][5884]). An `std::istream` already has a buffer: the get area of its `streambuf`
(`gptr()` to `egptr()`). The lexer now scans that window in bulk, keeps the current token as a pointer into it, and
copies only the part that is about to be refilled. Nothing is read ahead, so the stream is left exactly where it was
before. Reaching the protected get area takes no cast: member pointers formed in a class derived from
`std::streambuf`, so the access rule for protected members applies as intended. Before, parsing from an
`std::ifstream` took 1.8 to 2.5 times as long as reading the file into a string first; after #5828, it takes 11 to
18 % longer.
**`FILE*`** ([#5828][5828]). `std::fgetc` locks the `FILE` on every call. 3.13.0 locks it once per parse
(`flockfile`, then `getc_unlocked`; `_lock_file` and `_fgetc_nolock` with the Microsoft runtime). On macOS, this made
parsing `citm_catalog.json` from a `FILE*` 4.4 times as fast (34.1 ms to 7.8 ms). With glibc the gain was only 1.1 to
1.3×, because glibc's per-call locking is already cheap. The lock is held for the whole parse, which the documentation
now mentions, and both changes have opt-out macros.
## 2. Work on words, not bytes
The core of a JSON lexer is "copy bytes until something interesting happens". In a string, the interesting bytes are
the closing quote, a backslash, a control character, and anything above 0x7F (UTF-8). This test checks eight bytes at
once with ordinary 64-bit arithmetic:
```cpp
// return a word whose high bit is set in every byte of v that needs
// individual handling; zero if all 8 bytes can be copied as they are
inline std::uint64_t swar_string_special(std::uint64_t v) noexcept
{
constexpr std::uint64_t ones = 0x0101010101010101ull;
constexpr std::uint64_t high = 0x8080808080808080ull;
const std::uint64_t q = v ^ 0x2222222222222222ull; // '"'
const std::uint64_t b = v ^ 0x5C5C5C5C5C5C5C5Cull; // '\\'
const std::uint64_t has_quote = (q - ones) & ~q & high;
const std::uint64_t has_backslash = (b - ones) & ~b & high;
const std::uint64_t has_control = (v - 0x2020202020202020ull) & ~v & high; // < 0x20
const std::uint64_t has_non_ascii = v & high; // >= 0x80
return has_quote | has_backslash | has_control | has_non_ascii;
}
```
XOR with the quote turns every quote byte into zero, and `(x - 0x01…01) & ~x & 0x80…80` sets the high bit of the
bytes that were zero: the "determine if a word has a zero byte" trick from Sean Eron Anderson's
[Bit Twiddling Hacks](https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord). When the result is not
zero, the number of trailing zero bits divided by eight is the index of the first special byte. The subtraction can
also flag a byte *after* a real hit (a borrow), but never one before it, so the lowest flag is always right.
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_swar.svg"
</div>
The same kind of word test, written in standard C++11 with a `memcpy` load and a fallback for big-endian targets,
now runs in many places:
| where | what it skips | PR |
| --- | --- | --- |
| lexer: strings | runs of ordinary characters, and runs of well-formed multi-byte UTF-8 | [#5283][5283], [#5738][5738] |
| lexer: indentation | eight spaces per step after a newline, an idea from Glaze's `skip_matching_ws` | [#5810][5810] |
| lexer: numbers | eight digits per step, as fast_float does | [#5738][5738], [#5851][5851] |
| `dump()` | runs that need no escaping, with and without `ensure_ascii` | [#5285][5285] |
| `json_view` `dump()` | ASCII runs with `ensure_ascii` | [#5879][5879] |
Where a vector unit is part of the baseline instruction set (SSE2 on x86-64, NEON on 64-bit Arm), the string paths
use 16 bytes per step ([#5853][5853], [#5628][5628]). Non-ASCII text is validated 16 bytes at a time with simdjson's
"lookup4" UTF-8 check (Keiser and Lemire, 2021). That is the one place that needs more than the baseline: on x86-64
it uses SSSE3, which is checked once per process with `cpuid`. `JSON_NO_SIMD` turns all vector code off. On
`twitter.json`, #5853 made `json::parse()` 5 % faster with Clang and 9 % with GCC on an M1 Max; on long strings, 19
to 24 %.
**Short strings are a different problem.** Most keys and many values are short: `citm_catalog.json` averages 8 bytes
per string and `jeopardy.json` 14. For them, setting up a scan costs more than the scan. [#5878][5878] took the idea
of SQLite's `jsonAppendString()`: check each byte of a string of up to 32 bytes against a 256-entry table of bytes
that can be written unchanged, and copy the string in one go if they all pass. 32 bytes was the best threshold on the
M1; 16 gained less, and 64 lost again. [#5883][5883] then replaced the table, where SSE2 or NEON is available, with two
overlapping loads: a string of 16 to 32 characters is two 16-byte vectors that overlap in the middle, tested once and
stored with two stores, together with its quotes. That cut the instructions of `twitter.json`'s `dump()` by 21 %.
The table stays as the fallback for other targets.
**Escapes come from a table, too.** When the scanner stops at a quote, a backslash or a control character,
[#5822][5822] copies its escape sequence from a table of 8-byte rows (padded with zeros, length in the last byte)
straight into the write buffer: one 8-byte copy and one add, an idea from orjson's `QUOTE_TAB`. On an M1 Max, that
made dumping 100,000 log lines full of `\n`, `\t` and quotes 23 % faster. Most of that, the PR found, comes from
writing straight into the write buffer instead of going through an intermediate one; the table alone gained 2 to
7 %.
!!! note "Loop shape beats branch count"
Not every change in this direction worked the first time. The first version of [#5490][5490] removed one
branch per whitespace byte and made deeply nested `dump(4)` output parse 3.2 times *slower* with Clang. The
rewritten loop no longer let either compiler keep the input's read and end pointers in registers, so both
reloaded them from memory on every character. Restoring the original `do`-`while` shape, guarded by an `if`,
fixed it.
## 3. Own the number conversions
3.12.0 converted every floating-point number with `strtod` and every integer with `strtoull` or `strtoll`, after
copying the token into a buffer. `strtod` is correct, but general: it consults the locale for the decimal point, sets
`errno`, and handles any length of input.
`canada.json`, a GeoJSON file of 111,126 numbers, shows what that costs. 108,528 of its numbers have 16 to 19
significant digits, like `-65.613616999999977`. The classic shortcut, Clinger's fast path, needs the digits to fit
into the 53 bits of a `double` (at most 9,007,199,254,740,992) and the power of ten to be exact (at most 10²²): then a
single multiplication or division is correctly rounded. For most of `canada.json`'s numbers, the digits don't fit.
3.13.0 converts numbers itself, without the C library and without the locale:
```mermaid
flowchart TB
t["number token"] --> d{{"at most 19<br>significant digits?"}}
d -->|"yes"| c{{"digits and power of ten<br>exact as double?"}}
c -->|"yes"| cl["Clinger's fast path:<br>one multiplication or division"]
c -->|"no"| el["Eisel-Lemire:<br>128-bit integer arithmetic"]
d -->|"no"| el2["Eisel-Lemire on the first 19 digits"]
el2 --> amb{{"w and w+1 round<br>to the same double?"}}
amb -->|"yes"| done(["done"])
amb -->|"no"| big["compare with the exact midpoint<br>(big-integer arithmetic)"]
```
<p class="nj-caption" markdown>How 3.13.0 converts a decimal token to a `double`. Of `canada.json`'s 111,080 floating-point numbers, 9,742 take Clinger's fast path and 101,338 Eisel-Lemire; none has more than 19 digits.</p>
The Eisel-Lemire algorithm is adapted from fast_float's `compute_float` ([#5617][5617]), and it gives the correctly
rounded result for up to 19 digits without a fallback (Mushtak and Lemire, 2023). For longer numbers,
[#5738][5738] added fast_float's digit comparison. The table of 128-bit powers of five is fast_float's too. Then
[#5851][5851] stopped scanning the digits twice: the lexer now accumulates the value while it validates the token,
eight digits at a time with fast_float's `is_eight_digits` and `parse_eight_digits`, and a float of up to 19 digits
goes straight into the conversion with no call left on the way.
For output, 3.12.0 used Grisu2, which is fast but sometimes writes a 17th digit where 16 suffice.
[#5634][5634] ported [Żmij](https://github.com/vitaut/zmij) by Victor Zverovich to C++11. It writes the shortest
decimal that reads back as the same `double`, and the closest one if there are several. Its digit conversion, by
Xiang JunBo, turns eight digits into text per step, and the SIMD sequence by Dougall Johnson formats all 16 digits
in one vector register, decimal point included. The PR found one more stall on the way: the old code stored the
digits and immediately loaded them again shifted by one byte, and a load that overlaps two smaller stores can't be
forwarded from the store buffer. On an M1 Max, `dump()` of `canada.json` went from 6,987 µs to 2,405 µs (−66 %), and
on an x86-64 Haswell machine by −70 % (GCC 13) and −72 % (Clang 18).
That one is not free of visible change. Of one million random `double` bit patterns, 1,425 (0.14 %) are now written
differently: 810 with fewer digits (`5.3165205877497296e+16` becomes `5.31652058774973e+16`), 615 with the same
number of digits but the closer ones. They all read back as the same `double`, and none of one million short
decimals changes. In `canada.json`, 69 of the 111,126 numbers come out differently.
## 4. Don't do work nobody reads
A lot of what the 3.12.0 parser did was correct, cheap per call, and read by nobody in the common case.
- **The text of float tokens** ([#5852][5852]). The lexer copied every float token into a buffer so that a SAX
handler's `number_float(val, s)` could see the original text. That copy was about 10 % of parsing `canada.json`.
The built-in handlers behind `parse()` and `accept()` never look at it, so they now get an empty string, and the
lexer copies the text only for user handlers that might.
- **The token buffer** ([#5234][5234]). `get()` pushed every character into `token_string`, a buffer that only the
"last read" part of an error message uses. For contiguous input, the lexer now remembers where the token started and
rebuilds that text from the input if an error happens. The PR measured 8 % on its own benchmark; in the timeline,
parsing the indented `citm_catalog.json` got 35 % faster at that commit, because every space of the indentation
went through the buffer. [#5828][5828] did the same for streams, where the copy was about 20 % of the remaining
cost.
- **Positions** (#5809, above): lines and columns are counted only when an error message needs them.
- **Copies that should have been moves.** `from_cbor()` and the other binary readers ended with
`return res ? result : basic_json(value_t::discarded);`. The conditional operator's operand is an lvalue, so there
is no implicit move: every successfully parsed value was deep-copied once and then destroyed. Returning it by move
([#5501][5501]) took decoding a 2 MB CBOR document from 26.99 ms to 14.65 ms.
- **`ordered_json` growth** ([#5609][5609]). `ordered_json` stores its members in a
`std::vector<std::pair<const std::string, json>>`. Because the key is `const`, the pair's move constructor copies
the key and can throw, so `std::vector` copies every element when it grows, including the whole subtree of every
value. The library now grows that storage itself: keys copied, values moved. Parsing `twitter.json` into
`ordered_json` dropped from 60,456 to 19,182 allocations and from 3.20 ms to 1.70 ms.
- **Members that are inserted one at a time** ([#5882][5882]). The DOM parser now allocates each array once, at its
final size, and collects the members of an `ordered_json` object until the object is complete; big objects get
a hash table for the duplicate-key check. An object with very many members went
from 43 million instructions to 1.9 million. Since then, `ordered_json` parses 1 to 15 % *faster* than `json` in our suite, whose `std::map` still allocates a node per member.
!!! note "The same idea, measured twice"
Moving the key out of the lexer's buffer instead of copying it sounds like a free win. In September,
[#5458][5458] measured it: 3.5 % faster on `citm_catalog.json`, but 1.8 % slower on `jeopardy.json` and 11.9 %
slower on 40,000 short strings, so only string values were moved. In October, with much of the lexer around it
rewritten, [#5855][5855] measured again: `parse()` of `twitter.json` got 3.3 % faster, so keys are moved
now too. An idea that lost once is worth measuring again when the code around it changes.
## 5. Read the assembly
A good part of 3.13.0 came from reading the code the compiler produced for the hot loops, with Clang's
`-Rpass-missed=inline`, profiles, and instruction counts. A few things that turned up:
- **A stack canary on every token** ([#5854][5854]). The function that dispatches on the first byte of a token built
the expected text of `true`, `false` and `null` in local `std::array`s. With `-fstack-protector-strong`, the
default on Ubuntu, any local array gives the whole function a stack canary that is set and checked on every call:
the canary's load alone was 11 % of the function's samples. Now the literal is passed as a string literal with its
length as a template parameter. The same PR replaced the parser's `std::vector<bool>` nesting stack, whose
`push_back` GCC called out of line, with `std::vector<std::uint8_t>`.
- **Exceptions that block inlining** ([#5838][5838], [#5840][5840], [#5839][5839]). Building an exception message
inline (`concat(...)`, `create(...)`) made functions like `get_ref`, `operator[]` and the iterator operators too big
to inline. Moving construction and `throw` into never-inlined helpers fixed 27 sites. The same for the lifecycle:
Clang reported about 380 call sites where the copy constructor, the destructor or a comparison was not inlined,
even for a scalar. With the scalar case inline and the rest out of line, `j == 5` went from 3.55 ns to 0.65 ns
with Clang. It is not free: the probe translation unit grew by 13 % at `-O2`, and with GCC, `==` on large
documents got about 7 % slower.
- **Aliasing** ([#5633][5633]). Stores through a `char*` may alias anything, so a write position kept in a member is
reloaded after every store. `json_view`'s writer keeps it in a local variable instead.
- **Inlining that disappears** ([#5878][5878]). Once `dump_escaped()` had grown, GCC 13 and 16 stopped inlining two
small helpers into the pretty-printing loop, and indented output got up to 13 % slower. They are now forced inline.
- **Code size as a cost** ([#5902][5902]). `get<std::array<int, 1000>>()` used a pack expansion that compiled to one
function of about 28,000 instructions: a thousand inlined copies of the bounds and type checks. A loop needs 49.
!!! note "Instruction counts, not only time"
On the x86-64 machine we used for checking, moving code by a few bytes changed the time of unrelated benchmarks
by up to ±5 %. Many decisions in these PRs were therefore made on instruction counts (callgrind on Linux,
`/usr/bin/time -l` on macOS), checked against timings of builds with all functions and loops aligned to 64
bytes, and timed interleaved in one binary with several code layouts. The target, applied strictly in the later
PRs, was: at least 3 % faster, and no benchmark more than 1 % slower. Some PRs accepted a small loss elsewhere
and say so, such as the 7 % on GCC's `==` above.
## 6. Write through a cursor
In 3.12.0, every `dump()` created its output adapter with `std::make_shared`, and the serializer wrote every
structural character through a virtual call:
```cpp
o->write_characters("{\n", 2);
o->write_characters(indent_string.c_str(), new_indent);
o->write_character('\"');
```
The writing side changed in four steps:
```mermaid
flowchart LR
subgraph before["3.12.0"]
direction LR
d1["dump()"] --> a1["make_shared<br>output adapter"] --> v1["virtual call<br>per write"] --> s1[("std::string")]
end
subgraph after["3.13.0"]
direction LR
d2["dump()"] --> a2["adapter on<br>the stack"] --> b2["1 KiB buffer,<br>bulk append"] --> s2[("std::string")]
end
```
<p class="nj-caption" markdown>The text serializer's output path before and after [#5285][5285] and [#5449][5449].</p>
1. **A buffer in the serializer** ([#5285][5285]): all writes go into a 1 KiB buffer that is flushed in bulk, so the
virtual call happens once per KiB.
2. **No allocation per call** ([#5449][5449]): the adapter lives on the stack. Together with an indentation string
that [#5285][5285] creates only when needed, a compact `dump()` of a small object went from 4 heap allocations to
1, the returned string.
3. **Binary writers get a concrete sink** ([#5286][5286]): `to_cbor()` and friends write into a `std::vector` through
a value-type sink, with no virtual call. The same PR replaced `std::reverse` for byte order with
`__builtin_bswap*`, after finding that Clang had emitted no `bswap` instruction at all in the CBOR number path.
4. **A cursor instead of `vector::insert()`** ([#5824][5824], [#5885][5885]). After step 3, writing an array of
integers as CBOR was still no faster than in 3.12.0, and slower with GCC. The profile said why: each number's
one to eight bytes were appended with `vector::insert()`, an out-of-line insert-anywhere routine, which took 30 %
of the time. The sink now reserves space ahead and writes through a pointer, and runs of numbers are encoded in a
loop without a call per element.
The last step also took the branches out of encoding an integer. The size of each integer in a stream is hard to
predict, so the encoder looks the size class up from the number of leading zero bits and stores the head as one byte
plus one 8-byte word, of which the caller keeps only as many bytes as the class needs:
```cpp
// 1, 2, 3 or 4 if x fits 1, 2, 4 or 8 bytes, without a branch
static unsigned integer_size_class(const std::uint64_t x) noexcept
{
static constexpr std::array<std::uint8_t, 64> size_class_by_leading_zeros = { /* ... */ };
return size_class_by_leading_zeros[count_leading_zeros(x | 1u)];
}
std::size_t encode_first_byte_and_tail(CharType* out, std::uint8_t first_byte,
unsigned size_class, std::uint64_t value) const noexcept
{
out[0] = to_char_type(first_byte);
const unsigned unused_bits = 64u - ((8u << size_class) >> 1u);
const std::uint64_t tail = is_little_endian ? byteswap(value) >> unused_bits : value << unused_bits;
std::memcpy(out + 1, &tail, sizeof(tail)); // always 8 bytes; the caller keeps the first 0, 1, 2, 4 or 8
return ((std::size_t{1} << size_class) >> 1u) + 1;
}
```
Against 3.12.0, writing an array of small signed integers as CBOR went from 0.97× to 4.19× with Clang on an M1 Max,
and from 0.94× to 2.77× with GCC 13 on x86-64 ([#5824][5824]).
## 7. Fix the algorithm first
None of the micro-optimizations above matter much next to an algorithm that is quadratic. These are the ones found and
fixed in this release cycle, measured on the same machine:
| operation | 3.12.0 | 3.13.0 | speedup | cause | PR |
| --- | --: | --: | --: | --- | --- |
| `diff()` of an array of 64,000 numbers against an empty array | 4,102 ms | 9.98 ms | 411× | each `remove` was inserted at the front of the patch | [#5461][5461] |
| `diff()` of an array of 20,000 objects against every second one of them | 119 ms | 3.85 ms | 31× | the same | [#5461][5461] |
| `parse()` with a callback that rejects half of 32,000 objects | 1,334 ms | 11.5 ms | 116× | each rejected value was searched for from the start of its parent | [#5457][5457] |
| `<` on two equal values nested 24 levels deep (C++11 to C++17) | 62.6 ms | 0.002 ms | exponential | `std::vector`'s `<` asks `a < b` and `b < a`, and both recurse | [#5390][5390] |
| `<` on `citm_catalog.json` and a copy, 10× (C++11 to C++17) | 274 ms | 3.81 ms | 72× | the same | [#5390][5390] |
| `flatten()` of `citm_catalog.json` as `ordered_json` | 253 ms | 1.37 ms | 184× | every new key was looked up linearly | [#5834][5834] |
| `to_bson()` of a value nested 200 levels deep, 100× | 19.5 ms | 0.566 ms | 34× | each document's size was computed by walking everything below it again | [#5553][5553] |
| 100,000 × `push_back()` on an `ordered_json` with `JSON_DIAGNOSTICS` | 1,514 ms | 4.98 ms | 304× | every insert re-pointed the parent pointers of all elements | [#5832][5832] |
| 10,000 × `at(i)` on an `ordered_json` array with `JSON_DIAGNOSTICS` | 43.2 ms | 0.081 ms | 533× | the same | [#5832][5832] |
<div class="nj-fig-wrap" markdown>
--8<-- "images/perf_blog_cliffs.svg"
</div>
The `<` case matters to anyone who keeps `json` values in a `std::set`, uses them as `std::map` keys, or sorts them
before C++20. Each level of nesting doubled the work: two equal values nested 30 levels deep took 3.8 seconds to
compare in [#5390][5390]'s measurement, and nothing about such a value is unusual. Since C++20, `<` is derived from
`<=>`, which asks once.
The other side of this theme is recursion. A value nested 100,000 levels deep used to crash `dump()`, the copy
constructor, `==`, `hash`, `diff()`, `flatten()` and the binary writers with a stack overflow. The obvious fix,
making every walk iterative, measured 2 % to 20 % slower on ordinary documents ([#5285][5285]), 3 % to 9 % for
copying ([#5389][5389]), and 10 % to 14 % for merging ([#5547][5547]). RapidJSON keeps recursion as its default for
the same reason. 3.13.0 therefore bounds the recursion instead: the first 128 levels run the old recursive code, and
only below that does an explicit stack take over. A document nested less deeply pays only for counting the levels.
Destruction got its own trick ([#5762][5762]). Instead of a heap-allocated stack, the destructor uses pointer
reversal, the idea behind the Schorr-Waite graph marking algorithm: while it empties a container, that container's
last child slot stores the link back to its parent. Destroying any value now allocates nothing and never recurses.
Against 3.12.0, destroying a parsed document is 1.25 to 1.56 times as fast in our suite, and destroying an array of
one million small objects 1.39 times (125 ms to 90 ms).
## 8. Build a different data structure
After all of the above, `json::parse()` is still bound by what it builds: one heap allocation per string, array and
object, and a `std::map` node per member. Many programs only parse a document, read some fields and throw it away.
For them, 3.13.0 adds [`json_document`](../../features/json_view.md) and `json_view` in a new header,
`<nlohmann/json_view.hpp>`.
<div class="nj-fig-wrap" markdown>
--8<-- "images/json_view_layout.svg"
</div>
<p class="nj-caption" markdown>Top: the tree of separate heap allocations that `json::parse()` builds. Bottom: `json_document::parse()` keeps the source text and builds one flat index of 16-byte nodes that point back into it, plus a buffer of decoded strings.</p>
The design is not ours either. simdjson's tape and yyjson's immutable document are both flat arrays of fixed-size
entries in document order instead of trees of separate allocations, and yyjson's entries are 16 bytes, too. What
`json_document` does:
- **One 16-byte node per value and per key, in document order** ([#5620][5620]). Strings stay in the input; only
strings with escapes are decoded into an arena. Integers are converted while their digits are in the cache. A
container stores the size of its subtree, so a reader can step over it in constant time. A document makes a
handful of allocations, however many values it has.
- **Floats stay text until you read them.** The parser records where the integer digits, fraction and exponent are,
and converts on access with the same Clinger/Eisel-Lemire code as `json::parse`. We prototyped converting them
during the parse and dropped it ([#5908][5908]): reading every number of `canada.json` got 4 to 7 % faster, but
parsing it 36 to 90 % slower.
- **SIMD where the baseline has it** ([#5628][5628]): strings scanned 16 bytes at a time with SSE2 or NEON, and
non-ASCII text validated with simdjson's lookup4 check. `\u` escapes are decoded with a table, as yyjson's
`read_hex_u16` does.
- **A hash index for big objects** ([#5628][5628]): an object with 128 or more members gets an open-addressing
table after parsing, an idea from Boost.JSON. Looking up every key of a 10,000-member object went from 59.8 ms to
0.16 ms. The hash is not seeded, so the probe length is capped; if crafted keys exceed the cap, that object falls
back to a linear search, and parsing can't become quadratic.
- **First duplicate wins.** Lookups return the first of duplicate keys, as yyjson and simdjson do, because
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):
| 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 |
<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]).
It is not faster everywhere, and the harness ([#5627][5627], [#5914][5914]) is built to show where:
- **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.
## What didn't work
The PRs record the ideas that measured worse, which is as useful as the ones that made it:
| idea | result | where |
| --- | --- | --- |
| make every walk iterative | 2–20 % slower on ordinary documents | [#5285][5285], [#5389][5389], [#5547][5547] |
| move the key out of the lexer's reused buffer | 11.9 % slower (later a win, see above) | [#5458][5458] |
| inline `scan_literal()` | Clang's dispatch grew from 233 to 278 instructions and got slower | [#5854][5854] |
| short-string table for strings up to 64 bytes | lost against 32 | [#5878][5878] |
| leave the serializer's buffers uninitialized | timings moved 18 % apart in opposite directions on two similar workloads, so dropped; done later in [#5883][5883], where instruction counts showed 170 instructions saved per `dump()` | [#5285][5285] |
| out-of-line throw helpers for JSON Pointer lookups | no measurable gain, dropped | [#5836][5836] |
| `json_view`: an "all ASCII" flag per string | `dump()` with `ensure_ascii` faster, but parsing 1–13 % slower | [#5879][5879] |
| `json_view`: convert floats while parsing | `canada.json` parse 36–90 % slower | [#5908][5908] |
| `json_view`: note a large object inline in the parse loop | `canada.json` 37 % slower | [#5628][5628] |
| `json_view`: vector-scan every string in `set()` | 14–16 % slower on 16-byte strings | [#5926][5926] |
## Making fast paths safe
Fast paths are where the bugs are: they read in 8- and 16-byte steps, they skip validation that the slow path did, and
they are taken only for some inputs. A large part of these PRs is checking them:
- **Guard pages** ([#5826][5826]): the input is copied so that its last byte is the last readable byte of a page, and
the next page is unmapped. AddressSanitizer misses an over-read into the slack of the same heap allocation, and
fuzzers rarely end an input exactly at a page boundary; this test crashes on any over-read by one byte.
- **Differential fuzzing of the input kinds** ([#5827][5827]): every fuzz input is also parsed from an
`std::istringstream`, from `std::list` iterators (the byte path) and from a `FILE*`, and the value, the exception
id, the message and the byte offset must be identical.
- **Differential checks at scale**: 6.5 million float tokens against `strtod` including 60,000 exact halfway cases
([#5617][5617]); `json_view`'s batched float output byte-identical to the general writer for 10⁹ generated tokens
([#5908][5908]). For this post, we checked that 3.13.0 writes the same bytes as 3.12.0 in all five binary formats
for 39 test files, and the same JSON text for `twitter.json` and `citm_catalog.json`.
- **Mutation checks**: break the fast path on purpose (skip one byte too many, mark `"` as copyable) and make sure the
tests notice. In [#5878][5878], marking the quote as copyable fails 4,551 assertions.
## The price
None of this is free at compile time. `json.hpp` grew from 25,526 to 45,582 lines (`json_view.hpp` is a separate
header of 11,310 lines that you only pay for if you include it). Apple clang 21 at `-O2`, median of 9 compilations:
| translation unit | 3.12.0 | 3.13.0 | 3.13.0 with `JSON_NO_AUTOMATIC_UDLS` |
| --- | --: | --: | --: |
| only includes `json.hpp` | 528 ms | 709 ms (+34 %) | 508 ms (−4 %) |
| parses, dumps and writes CBOR | 1,175 ms | 1,885 ms (+60 %) | 1,858 ms (+58 %) |
We have not broken the second row down by change. [`JSON_NO_AUTOMATIC_UDLS`](../../api/macros/json_no_automatic_udls.md) moves the
`_json` literals into their own header and more than makes up for the first row; the
[compile-time page](../../integration/compile_times.md) lists the other options.
## How we measured
**What is compared.** "3.12.0" is the released single header. "3.13.0" is `develop` at
[84c542164](https://github.com/nlohmann/json/commit/84c5421644) with seven of the maintainer's open, non-draft pull requests that touch code
merged in ([#5890][5890], [#5908][5908], [#5914][5914], [#5926][5926], [#5936][5936], [#5945][5945],
[#5947][5947]) and amalgamated. Merging #5890 onto today's `develop` left one duplicate member declaration, which we
removed; nothing else was changed. Both are compiled from the *same* benchmark source, the Google Benchmark suite in
[`tests/benchmarks`](https://github.com/nlohmann/json/tree/develop/tests/benchmarks), with the BON8 benchmarks
removed because 3.12.0 has no BON8.
| | |
| --- | --- |
| machine | Apple M1 Max laptop on AC power, macOS 27.0.1 |
| compiler | Apple clang 21, libc++ |
| flags | `-O3 -flto -DNDEBUG`, the compiler's default standard, C++14 (the timeline and `json_view` comparisons: C++17, `-O3`, no LTO) |
| suite | 2 rounds × 4 repetitions per version, random interleaving, each round started only when the load average was below 4; the median of all 8 |
| noise | the coefficient of variation was 3 % or less for 176 of the 182 rows with 3.12.0 and 178 with 3.13.0; the largest was 12 % |
| inputs | `twitter.json`, `citm_catalog.json` and `canada.json` from [nativejson-benchmark](https://github.com/miloyip/nativejson-benchmark), a 56 MB `jeopardy.json`, and number-heavy files |
The cliffs come from small extra programs (C++17, `-O3`, median of 3 interleaved runs). The timeline is
[`tests/benchmarks/history`](https://github.com/nlohmann/json/tree/develop/tests/benchmarks/history): one program,
compiled against `single_include` of 3.12.0, of each of the 315 commits on `develop` that changed `json.hpp` or `json_view.hpp` since, and of the candidate, 4 rounds in random order, median of
the rounds. The `json_view` comparison is
[`tests/benchmarks/json_view/compare.py`](https://github.com/nlohmann/json/tree/develop/tests/benchmarks/json_view)
with pinned downloads of yyjson 0.13.0, simdjson 4.6.11 and Boost.JSON 1.92.0, 30 interleaved rounds, best round;
every engine must produce the same values, strings and sums of numbers before anything is timed.
**What we did not measure.** All of our numbers are from one Apple silicon laptop with Clang. The PRs quote numbers
from an x86-64 Haswell server with GCC 13 and Clang 18 where they had them; that server shares its cores with other
work, so we did not run a second set of tables there and quote its timings only where a PR did. Expect smaller
gains for some workloads on x86-64 with glibc: its `FILE*` locking is cheaper to begin with, and its allocator
behaves differently. We did not test Windows for speed at all.
## Thanks
Most of what is in this post was invented by other people. The libraries and papers we took ideas or code from, in
the order they appear above:
- [serde_json](https://github.com/serde-rs/json): deriving positions from the offset only on error.
- Sean Eron Anderson's [Bit Twiddling Hacks](https://graphics.stanford.edu/~seander/bithacks.html): the zero-byte
test behind every word-at-a-time scan.
- [Glaze](https://github.com/stephenberry/glaze): skipping indentation in 8-byte steps (`skip_matching_ws`).
- [simdjson](https://github.com/simdjson/simdjson) by Daniel Lemire, Geoff Langdale, John Keiser and contributors:
the "lookup4" UTF-8 check (J. Keiser and D. Lemire, "Validating UTF-8 In Less Than One Instruction Per Byte",
2021), and the tape that showed what a flat index can do.
- [SQLite](https://sqlite.org)'s `jsonAppendString()`: writing short strings with a table loop.
- [orjson](https://github.com/ijl/orjson)'s `QUOTE_TAB`: escape sequences as fixed-size table rows.
- [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors: the Eisel-Lemire
algorithm, its table of powers of five, its digit comparison, and eight digits at a time (N. Mushtak and D. Lemire,
"Fast number parsing without fallback", 2023). W. D. Clinger for the fast path, M. Eisel for the algorithm.
- [Żmij](https://github.com/vitaut/zmij) by Victor Zverovich, with the digit conversion of Xiang JunBo and the SIMD
sequence of Dougall Johnson.
- [Boost.JSON](https://github.com/boostorg/json): switching to a hash table for large objects.
- [yyjson](https://github.com/ibireme/yyjson) by YaoYuan: table-driven `\u` decoding, fixed-offset unrolled checks,
and a 16-byte flat document to measure against.
- [RapidJSON](https://github.com/Tencent/rapidjson): the measured reason to keep recursion as the default.
And the people who sent or shaped pull requests: [@gregmarr](https://github.com/gregmarr) reviewed most of them and
suggested the sized-sentinel fast path, the peek design for exact stream positions, one SIMD switch for the whole
library, and the vector check of `json_view`'s strings on edit; [@veselink1](https://github.com/veselink1) and
[@michaelsam94](https://github.com/michaelsam94) wrote the allocator and exception-safety fixes for the destructor
that [#5762][5762] took over (the non-recursive destructor itself goes back to
[#1436](https://github.com/nlohmann/json/pull/1436) by [@nickaein](https://github.com/nickaein) in 2019);
[@commit-msuyog](https://github.com/commit-msuyog) gave the 128-bit multiplication behind Eisel-Lemire MSVC
intrinsics ([#5782][5782]); [@ayush-singh-0601](https://github.com/ayush-singh-0601) started the fix for deep values in the binary writers;
[@avionicharshit-byte](https://github.com/avionicharshit-byte) made `diff()` linear for shrinking arrays
([#5461][5461]); [@mvanslobbe](https://github.com/mvanslobbe) sped up the parser's separator check ([#5592][5592]);
and [@alexprabhat99](https://github.com/alexprabhat99) removed the temporary values behind CBOR and MessagePack
object keys ([#5328][5328]).
`twitter.json`, `citm_catalog.json` and `canada.json` come from Milo Yip's
[nativejson-benchmark](https://github.com/miloyip/nativejson-benchmark).
[5185]: https://github.com/nlohmann/json/pull/5185
[5234]: https://github.com/nlohmann/json/pull/5234
[5283]: https://github.com/nlohmann/json/pull/5283
[5285]: https://github.com/nlohmann/json/pull/5285
[5286]: https://github.com/nlohmann/json/pull/5286
[5328]: https://github.com/nlohmann/json/pull/5328
[5389]: https://github.com/nlohmann/json/pull/5389
[5390]: https://github.com/nlohmann/json/pull/5390
[5449]: https://github.com/nlohmann/json/pull/5449
[5457]: https://github.com/nlohmann/json/pull/5457
[5458]: https://github.com/nlohmann/json/pull/5458
[5461]: https://github.com/nlohmann/json/pull/5461
[5490]: https://github.com/nlohmann/json/pull/5490
[5501]: https://github.com/nlohmann/json/pull/5501
[5547]: https://github.com/nlohmann/json/pull/5547
[5553]: https://github.com/nlohmann/json/pull/5553
[5592]: https://github.com/nlohmann/json/pull/5592
[5609]: https://github.com/nlohmann/json/pull/5609
[5617]: https://github.com/nlohmann/json/pull/5617
[5620]: https://github.com/nlohmann/json/pull/5620
[5622]: https://github.com/nlohmann/json/pull/5622
[5627]: https://github.com/nlohmann/json/pull/5627
[5628]: https://github.com/nlohmann/json/pull/5628
[5633]: https://github.com/nlohmann/json/pull/5633
[5634]: https://github.com/nlohmann/json/pull/5634
[5738]: https://github.com/nlohmann/json/pull/5738
[5741]: https://github.com/nlohmann/json/pull/5741
[5746]: https://github.com/nlohmann/json/pull/5746
[5762]: https://github.com/nlohmann/json/pull/5762
[5809]: https://github.com/nlohmann/json/pull/5809
[5810]: https://github.com/nlohmann/json/pull/5810
[5822]: https://github.com/nlohmann/json/pull/5822
[5824]: https://github.com/nlohmann/json/pull/5824
[5826]: https://github.com/nlohmann/json/pull/5826
[5827]: https://github.com/nlohmann/json/pull/5827
[5828]: https://github.com/nlohmann/json/pull/5828
[5832]: https://github.com/nlohmann/json/pull/5832
[5834]: https://github.com/nlohmann/json/pull/5834
[5835]: https://github.com/nlohmann/json/pull/5835
[5836]: https://github.com/nlohmann/json/pull/5836
[5838]: https://github.com/nlohmann/json/pull/5838
[5839]: https://github.com/nlohmann/json/pull/5839
[5840]: https://github.com/nlohmann/json/pull/5840
[5851]: https://github.com/nlohmann/json/pull/5851
[5852]: https://github.com/nlohmann/json/pull/5852
[5853]: https://github.com/nlohmann/json/pull/5853
[5854]: https://github.com/nlohmann/json/pull/5854
[5855]: https://github.com/nlohmann/json/pull/5855
[5878]: https://github.com/nlohmann/json/pull/5878
[5879]: https://github.com/nlohmann/json/pull/5879
[5882]: https://github.com/nlohmann/json/pull/5882
[5883]: https://github.com/nlohmann/json/pull/5883
[5884]: https://github.com/nlohmann/json/pull/5884
[5885]: https://github.com/nlohmann/json/pull/5885
[5890]: https://github.com/nlohmann/json/pull/5890
[5902]: https://github.com/nlohmann/json/pull/5902
[5908]: https://github.com/nlohmann/json/pull/5908
[5914]: https://github.com/nlohmann/json/pull/5914
[5926]: https://github.com/nlohmann/json/pull/5926
[5936]: https://github.com/nlohmann/json/pull/5936
[5945]: https://github.com/nlohmann/json/pull/5945
[5947]: https://github.com/nlohmann/json/pull/5947
@@ -0,0 +1,67 @@
<svg class="nj-fig nj-charts nj-charts--blog" viewBox="0 0 600 364" role="img" aria-labelledby="nj-blog-cliffs nj-blog-cliffs-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-cliffs">Operations that grew quadratically or worse: time with 3.12.0 and 3.13.0, log scale</title>
<desc id="nj-blog-cliffs-d">Dot plot on a logarithmic time axis. diff() 64k numbers vs []: 4102 ms to 9.98 ms; diff() 20k objects vs half: 119 ms to 3.85 ms; parse() callback, 32k objects: 1334 ms to 11.5 ms; &lt; nested 24 deep: 62.6 ms to 0.002 ms; &lt; citm, 10x: 274 ms to 3.81 ms; flatten() citm, ordered_json: 253 ms to 1.37 ms; to_bson() 200 deep, 100x: 19.5 ms to 0.566 ms; push_back() 100k, diagnostics: 1514 ms to 4.98 ms; at(i) 10k, diagnostics: 43.2 ms to 0.081 ms.</desc>
<line class="nj-charts-grid" x1="250" y1="30" x2="250" y2="336"/>
<text class="nj-charts-tick" x="250" y="352">1 µs</text>
<line class="nj-charts-grid" x1="297.857" y1="30" x2="297.857" y2="336"/>
<text class="nj-charts-tick" x="297.857" y="352">10 µs</text>
<line class="nj-charts-grid" x1="345.714" y1="30" x2="345.714" y2="336"/>
<text class="nj-charts-tick" x="345.714" y="352">0.1 ms</text>
<line class="nj-charts-grid" x1="393.571" y1="30" x2="393.571" y2="336"/>
<text class="nj-charts-tick" x="393.571" y="352">1 ms</text>
<line class="nj-charts-grid" x1="441.429" y1="30" x2="441.429" y2="336"/>
<text class="nj-charts-tick" x="441.429" y="352">10 ms</text>
<line class="nj-charts-grid" x1="489.286" y1="30" x2="489.286" y2="336"/>
<text class="nj-charts-tick" x="489.286" y="352">0.1 s</text>
<line class="nj-charts-grid" x1="537.143" y1="30" x2="537.143" y2="336"/>
<text class="nj-charts-tick" x="537.143" y="352">1 s</text>
<line class="nj-charts-grid" x1="585" y1="30" x2="585" y2="336"/>
<text class="nj-charts-tick" x="585" y="352">10 s</text>
<circle class="nj-charts-ojson-dot" cx="250" cy="14" r="5"/><text class="nj-charts-leg" x="260" y="18.5">3.12.0</text>
<circle class="nj-charts-json-dot" cx="330" cy="14" r="5"/><text class="nj-charts-leg" x="340" y="18.5">3.13.0</text>
<text class="nj-charts-rowlabel" x="240" y="52" text-anchor="end">diff() 64k numbers vs []</text>
<line class="nj-charts-axis" x1="441.387" y1="48" x2="566.479" y2="48"/>
<circle class="nj-charts-ojson-dot" cx="566.479" cy="48" r="5"><title>diff() 64k numbers vs [], 3.12.0: 4102 ms</title></circle>
<circle class="nj-charts-json-dot" cx="441.387" cy="48" r="5"><title>diff() 64k numbers vs [], 3.13.0: 9.98 ms</title></circle>
<text class="nj-charts-factor" x="503.933" y="41">411&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="86" text-anchor="end">diff() 20k objects vs half</text>
<line class="nj-charts-axis" x1="421.59" y1="82" x2="492.901" y2="82"/>
<circle class="nj-charts-ojson-dot" cx="492.901" cy="82" r="5"><title>diff() 20k objects vs half, 3.12.0: 119 ms</title></circle>
<circle class="nj-charts-json-dot" cx="421.59" cy="82" r="5"><title>diff() 20k objects vs half, 3.13.0: 3.85 ms</title></circle>
<text class="nj-charts-factor" x="457.246" y="75">31&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="120" text-anchor="end">parse() callback, 32k objects</text>
<line class="nj-charts-axis" x1="444.333" y1="116" x2="543.132" y2="116"/>
<circle class="nj-charts-ojson-dot" cx="543.132" cy="116" r="5"><title>parse() callback, 32k objects, 3.12.0: 1334 ms</title></circle>
<circle class="nj-charts-json-dot" cx="444.333" cy="116" r="5"><title>parse() callback, 32k objects, 3.13.0: 11.5 ms</title></circle>
<text class="nj-charts-factor" x="493.733" y="109">116&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="154" text-anchor="end">&lt; nested 24 deep</text>
<line class="nj-charts-axis" x1="264.406" y1="150" x2="479.55" y2="150"/>
<circle class="nj-charts-ojson-dot" cx="479.55" cy="150" r="5"><title>&lt; nested 24 deep, 3.12.0: 62.6 ms</title></circle>
<circle class="nj-charts-json-dot" cx="264.406" cy="150" r="5"><title>&lt; nested 24 deep, 3.13.0: 0.002 ms</title></circle>
<text class="nj-charts-factor" x="371.978" y="143">31300&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="188" text-anchor="end">&lt; citm, 10x</text>
<line class="nj-charts-axis" x1="421.373" y1="184" x2="510.235" y2="184"/>
<circle class="nj-charts-ojson-dot" cx="510.235" cy="184" r="5"><title>&lt; citm, 10x, 3.12.0: 274 ms</title></circle>
<circle class="nj-charts-json-dot" cx="421.373" cy="184" r="5"><title>&lt; citm, 10x, 3.13.0: 3.81 ms</title></circle>
<text class="nj-charts-factor" x="465.804" y="177">72&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="222" text-anchor="end">flatten() citm, ordered_json</text>
<line class="nj-charts-axis" x1="400.114" y1="218" x2="508.578" y2="218"/>
<circle class="nj-charts-ojson-dot" cx="508.578" cy="218" r="5"><title>flatten() citm, ordered_json, 3.12.0: 253 ms</title></circle>
<circle class="nj-charts-json-dot" cx="400.114" cy="218" r="5"><title>flatten() citm, ordered_json, 3.13.0: 1.37 ms</title></circle>
<text class="nj-charts-factor" x="454.346" y="211">185&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="256" text-anchor="end">to_bson() 200 deep, 100x</text>
<line class="nj-charts-axis" x1="381.742" y1="252" x2="455.309" y2="252"/>
<circle class="nj-charts-ojson-dot" cx="455.309" cy="252" r="5"><title>to_bson() 200 deep, 100x, 3.12.0: 19.5 ms</title></circle>
<circle class="nj-charts-json-dot" cx="381.742" cy="252" r="5"><title>to_bson() 200 deep, 100x, 3.13.0: 0.566 ms</title></circle>
<text class="nj-charts-factor" x="418.525" y="245">34&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="290" text-anchor="end">push_back() 100k, diagnostics</text>
<line class="nj-charts-axis" x1="426.939" y1="286" x2="545.763" y2="286"/>
<circle class="nj-charts-ojson-dot" cx="545.763" cy="286" r="5"><title>push_back() 100k, diagnostics, 3.12.0: 1514 ms</title></circle>
<circle class="nj-charts-json-dot" cx="426.939" cy="286" r="5"><title>push_back() 100k, diagnostics, 3.13.0: 4.98 ms</title></circle>
<text class="nj-charts-factor" x="486.351" y="279">304&#215;</text>
<text class="nj-charts-rowlabel" x="240" y="324" text-anchor="end">at(i) 10k, diagnostics</text>
<line class="nj-charts-axis" x1="341.335" y1="320" x2="471.841" y2="320"/>
<circle class="nj-charts-ojson-dot" cx="471.841" cy="320" r="5"><title>at(i) 10k, diagnostics, 3.12.0: 43.2 ms</title></circle>
<circle class="nj-charts-json-dot" cx="341.335" cy="320" r="5"><title>at(i) 10k, diagnostics, 3.13.0: 0.081 ms</title></circle>
<text class="nj-charts-factor" x="406.588" y="313">533&#215;</text>
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

@@ -0,0 +1,87 @@
<svg class="nj-fig nj-charts nj-charts--blog" viewBox="0 0 560 614" role="img" aria-labelledby="nj-blog-overview nj-blog-overview-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-overview">Speedup of 3.13.0 over 3.12.0 per workload, Apple M1 Max, Apple clang</title>
<desc id="nj-blog-overview-d">Horizontal bars, longer is faster. twitter.json 3.0x; citm_catalog.json 4.1x; canada.json 3.5x; canada.json, indented 6.7x; citm, ordered_json 6.6x; twitter, std::ifstream 2.5x; citm, FILE* 4.8x; citm, accept() 7.0x; dump() twitter 6.7x; dump() canada 3.0x; dump(4) citm 4.6x; to_cbor() twitter 4.5x; twitter, memory 3.1x; twitter, FILE* 6.3x; diff() canada 10x; iterate canada 2.7x; copy + destroy citm 1.11x; == citm 1.04x.</desc>
<text class="nj-charts-panel" x="8" y="46">Parsing</text>
<text class="nj-charts-panel" x="8" y="270">Writing</text>
<text class="nj-charts-panel" x="8" y="398">Reading C&#8203;BOR</text>
<text class="nj-charts-panel" x="8" y="478">Values</text>
<line class="nj-charts-grid" x1="220" y1="34" x2="220" y2="586"/>
<text class="nj-charts-tick" x="220" y="602">1&#215;</text>
<line class="nj-charts-grid" x1="250" y1="34" x2="250" y2="586"/>
<text class="nj-charts-tick" x="250" y="602">2&#215;</text>
<line class="nj-charts-grid" x1="280" y1="34" x2="280" y2="586"/>
<text class="nj-charts-tick" x="280" y="602">3&#215;</text>
<line class="nj-charts-grid" x1="310" y1="34" x2="310" y2="586"/>
<text class="nj-charts-tick" x="310" y="602">4&#215;</text>
<line class="nj-charts-grid" x1="340" y1="34" x2="340" y2="586"/>
<text class="nj-charts-tick" x="340" y="602">5&#215;</text>
<line class="nj-charts-grid" x1="370" y1="34" x2="370" y2="586"/>
<text class="nj-charts-tick" x="370" y="602">6&#215;</text>
<line class="nj-charts-grid" x1="400" y1="34" x2="400" y2="586"/>
<text class="nj-charts-tick" x="400" y="602">7&#215;</text>
<line class="nj-charts-grid" x1="430" y1="34" x2="430" y2="586"/>
<text class="nj-charts-tick" x="430" y="602">8&#215;</text>
<line class="nj-charts-grid" x1="460" y1="34" x2="460" y2="586"/>
<text class="nj-charts-tick" x="460" y="602">9&#215;</text>
<line class="nj-charts-grid" x1="490" y1="34" x2="490" y2="586"/>
<text class="nj-charts-tick" x="490" y="602">10&#215;</text>
<line class="nj-charts-grid" x1="520" y1="34" x2="520" y2="586"/>
<text class="nj-charts-tick" x="520" y="602">11&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="68" text-anchor="end">twitter.json</text>
<path class="nj-charts-c1" d="M190 56 H276.6 Q280.6 56 280.6 60 V67 Q280.6 71 276.6 71 H190 Z"><title>twitter.json: 3.0&#215;</title></path>
<text class="nj-charts-val" x="285.6" y="68">3.0&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="92" text-anchor="end">citm_catalog.json</text>
<path class="nj-charts-c1" d="M190 80 H309.9 Q313.9 80 313.9 84 V91 Q313.9 95 309.9 95 H190 Z"><title>citm_catalog.json: 4.1&#215;</title></path>
<text class="nj-charts-val" x="318.9" y="92">4.1&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="116" text-anchor="end">canada.json</text>
<path class="nj-charts-c1" d="M190 104 H289.8 Q293.8 104 293.8 108 V115 Q293.8 119 289.8 119 H190 Z"><title>canada.json: 3.5&#215;</title></path>
<text class="nj-charts-val" x="298.8" y="116">3.5&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="140" text-anchor="end">canada.json, indented</text>
<path class="nj-charts-c1" d="M190 128 H388.2 Q392.2 128 392.2 132 V139 Q392.2 143 388.2 143 H190 Z"><title>canada.json, indented: 6.7&#215;</title></path>
<text class="nj-charts-val" x="397.2" y="140">6.7&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="164" text-anchor="end">citm, ordered_json</text>
<path class="nj-charts-c1" d="M190 152 H383.4 Q387.4 152 387.4 156 V163 Q387.4 167 383.4 167 H190 Z"><title>citm, ordered_json: 6.6&#215;</title></path>
<text class="nj-charts-val" x="392.4" y="164">6.6&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="188" text-anchor="end">twitter, std::ifstream</text>
<path class="nj-charts-c1" d="M190 176 H259.8 Q263.8 176 263.8 180 V187 Q263.8 191 259.8 191 H190 Z"><title>twitter, std::ifstream: 2.5&#215;</title></path>
<text class="nj-charts-val" x="268.8" y="188">2.5&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="212" text-anchor="end">citm, FILE*</text>
<path class="nj-charts-c1" d="M190 200 H328.8 Q332.8 200 332.8 204 V211 Q332.8 215 328.8 215 H190 Z"><title>citm, FILE*: 4.8&#215;</title></path>
<text class="nj-charts-val" x="337.8" y="212">4.8&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="236" text-anchor="end">citm, accept()</text>
<path class="nj-charts-c1" d="M190 224 H395.7 Q399.7 224 399.7 228 V235 Q399.7 239 395.7 239 H190 Z"><title>citm, accept(): 7.0&#215;</title></path>
<text class="nj-charts-val" x="404.7" y="236">7.0&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="292" text-anchor="end">dump() twitter</text>
<path class="nj-charts-c1" d="M190 280 H386.1 Q390.1 280 390.1 284 V291 Q390.1 295 386.1 295 H190 Z"><title>dump() twitter: 6.7&#215;</title></path>
<text class="nj-charts-val" x="395.1" y="292">6.7&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="316" text-anchor="end">dump() canada</text>
<path class="nj-charts-c1" d="M190 304 H274.5 Q278.5 304 278.5 308 V315 Q278.5 319 274.5 319 H190 Z"><title>dump() canada: 3.0&#215;</title></path>
<text class="nj-charts-val" x="283.5" y="316">3.0&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="340" text-anchor="end">dump(4) citm</text>
<path class="nj-charts-c1" d="M190 328 H324.9 Q328.9 328 328.9 332 V339 Q328.9 343 324.9 343 H190 Z"><title>dump(4) citm: 4.6&#215;</title></path>
<text class="nj-charts-val" x="333.9" y="340">4.6&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="364" text-anchor="end">to_cbor() twitter</text>
<path class="nj-charts-c1" d="M190 352 H321 Q325 352 325 356 V363 Q325 367 321 367 H190 Z"><title>to_cbor() twitter: 4.5&#215;</title></path>
<text class="nj-charts-val" x="330" y="364">4.5&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="420" text-anchor="end">twitter, memory</text>
<path class="nj-charts-c1" d="M190 408 H279.3 Q283.3 408 283.3 412 V419 Q283.3 423 279.3 423 H190 Z"><title>twitter, memory: 3.1&#215;</title></path>
<text class="nj-charts-val" x="288.3" y="420">3.1&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="444" text-anchor="end">twitter, FILE*</text>
<path class="nj-charts-c1" d="M190 432 H375.3 Q379.3 432 379.3 436 V443 Q379.3 447 375.3 447 H190 Z"><title>twitter, FILE*: 6.3&#215;</title></path>
<text class="nj-charts-val" x="384.3" y="444">6.3&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="500" text-anchor="end">diff() canada</text>
<path class="nj-charts-c1" d="M190 488 H499.2 Q503.2 488 503.2 492 V499 Q503.2 503 499.2 503 H190 Z"><title>diff() canada: 10&#215;</title></path>
<text class="nj-charts-val" x="508.2" y="500">10&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="524" text-anchor="end">iterate canada</text>
<path class="nj-charts-c1" d="M190 512 H266.7 Q270.7 512 270.7 516 V523 Q270.7 527 266.7 527 H190 Z"><title>iterate canada: 2.7&#215;</title></path>
<text class="nj-charts-val" x="275.7" y="524">2.7&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="548" text-anchor="end">copy + destroy citm</text>
<path class="nj-charts-c1" d="M190 536 H219.3 Q223.3 536 223.3 540 V547 Q223.3 551 219.3 551 H190 Z"><title>copy + destroy citm: 1.11&#215;</title></path>
<text class="nj-charts-val" x="228.3" y="548">1.11&#215;</text>
<text class="nj-charts-rowlabel nj-charts-tick--r" x="182" y="572" text-anchor="end">== citm</text>
<path class="nj-charts-c1" d="M190 560 H217.2 Q221.2 560 221.2 564 V571 Q221.2 575 217.2 575 H190 Z"><title>== citm: 1.04&#215;</title></path>
<text class="nj-charts-val" x="226.2" y="572">1.04&#215;</text>
<line class="nj-charts-ref" x1="220" y1="34" x2="220" y2="586"/>
<line class="nj-charts-zero" x1="190" y1="34" x2="190" y2="586"/>
<text class="nj-charts-note" x="190" y="18">speedup over 3.12.0 (the line at 1&#215; is 3.12.0)</text>
</svg>

After

Width:  |  Height:  |  Size: 8.2 KiB

@@ -0,0 +1,60 @@
<svg class="nj-fig nj-charts nj-charts--swar" viewBox="0 0 640 312" role="img" aria-labelledby="nj-blog-swar nj-blog-swar-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-swar">Finding the end of a run of ordinary string characters eight bytes at a time</title>
<desc id="nj-blog-swar-d">The eight bytes w, i, t, t, e, r, quote and comma are loaded as one word. The test sets the high bit only in byte 6, the quote. Counting trailing zero bits gives 55, divided by eight gives 6: bytes 0 to 5 are copied at once, then the quote ends the string.</desc>
<text class="fg-h" x="40" y="20">eight input bytes, loaded as one 64-bit word (byte 0 is the lowest)</text>
<rect class="fg-cell" x="40" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="72" y="60" text-anchor="middle">w</text>
<text class="nj-charts-tick" x="72" y="92">0x77</text>
<text class="nj-charts-tick" x="72" y="108">byte 0</text>
<rect class="fg-cell" x="110" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="142" y="60" text-anchor="middle">i</text>
<text class="nj-charts-tick" x="142" y="92">0x69</text>
<text class="nj-charts-tick" x="142" y="108">byte 1</text>
<rect class="fg-cell" x="180" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="212" y="60" text-anchor="middle">t</text>
<text class="nj-charts-tick" x="212" y="92">0x74</text>
<text class="nj-charts-tick" x="212" y="108">byte 2</text>
<rect class="fg-cell" x="250" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="282" y="60" text-anchor="middle">t</text>
<text class="nj-charts-tick" x="282" y="92">0x74</text>
<text class="nj-charts-tick" x="282" y="108">byte 3</text>
<rect class="fg-cell" x="320" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="352" y="60" text-anchor="middle">e</text>
<text class="nj-charts-tick" x="352" y="92">0x65</text>
<text class="nj-charts-tick" x="352" y="108">byte 4</text>
<rect class="fg-cell" x="390" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="422" y="60" text-anchor="middle">r</text>
<text class="nj-charts-tick" x="422" y="92">0x72</text>
<text class="nj-charts-tick" x="422" y="108">byte 5</text>
<rect class="fg-cell" x="460" y="34" width="64" height="40" rx="4"/>
<rect class="nj-charts-c2" fill-opacity=".25" x="460" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="492" y="60" text-anchor="middle">&quot;</text>
<text class="nj-charts-tick" x="492" y="92">0x22</text>
<text class="nj-charts-tick" x="492" y="108">byte 6</text>
<rect class="fg-cell" x="530" y="34" width="64" height="40" rx="4"/>
<text class="fg-code" x="562" y="60" text-anchor="middle">,</text>
<text class="nj-charts-tick" x="562" y="92">0x2C</text>
<text class="nj-charts-tick" x="562" y="108">byte 7</text>
<text class="fg-h" x="40" y="132">swar_string_special(): the high bit of each byte that needs handling</text>
<rect class="fg-cell" x="40" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="72" y="169" text-anchor="middle">0x00</text>
<rect class="fg-cell" x="110" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="142" y="169" text-anchor="middle">0x00</text>
<rect class="fg-cell" x="180" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="212" y="169" text-anchor="middle">0x00</text>
<rect class="fg-cell" x="250" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="282" y="169" text-anchor="middle">0x00</text>
<rect class="fg-cell" x="320" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="352" y="169" text-anchor="middle">0x00</text>
<rect class="fg-cell" x="390" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="422" y="169" text-anchor="middle">0x00</text>
<rect class="fg-cell" x="460" y="146" width="64" height="34" rx="4"/>
<rect class="nj-charts-c2" fill-opacity=".25" x="460" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="492" y="169" text-anchor="middle">0x80</text>
<rect class="fg-cell" x="530" y="146" width="64" height="34" rx="4"/>
<text class="fg-code" x="562" y="169" text-anchor="middle">0x00</text>
<text class="fg-code" x="40" y="216">count_trailing_zeros(0x0080000000000000) = 55</text>
<text class="fg-code" x="40" y="242">55 / 8 = 6: copy bytes 0 to 5 in one go, then handle the quote</text>
<text class="fg-note fg-note--l" x="40" y="272">No branch per byte: a few subtractions, ANDs and ORs per word,</text>
<text class="fg-note fg-note--l" x="40" y="290">then one count of trailing zeros.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -0,0 +1,37 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-accept_twitter nj-blog-tl-accept_twitter-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-accept_twitter">accept() twitter.json: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-accept_twitter-d">accept() twitter.json: speedup over 3.12.0 at each of 317 commits, ending at 5.0x. Labeled steps: #5234, #5283, #5592, #5809, #5810, #5853.</desc>
<text class="nj-charts-panel" x="8" y="18">accept() twitter.json</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="159.333" x2="330" y2="159.333"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="163.333">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="110.667" x2="330" y2="110.667"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="114.667">4&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">8&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,208.1 45.8,208.1 45.8,207.8 46.7,207.8 46.7,208.0 47.6,208.0 47.6,207.7 48.5,207.7 48.5,207.9 49.4,207.9 49.4,208.0 50.3,208.0 50.3,208.1 51.2,208.1 51.2,208.4 52.1,208.4 52.1,207.1 53.1,207.1 53.1,207.9 54.0,207.9 54.0,208.2 54.9,208.2 54.9,207.9 55.8,207.9 55.8,207.9 56.7,207.9 56.7,207.7 57.6,207.7 57.6,207.9 58.5,207.9 58.5,207.8 59.4,207.8 59.4,207.7 60.3,207.7 60.3,208.2 61.2,208.2 61.2,207.2 62.1,207.2 62.1,208.0 63.0,208.0 63.0,208.0 63.9,208.0 63.9,207.8 64.8,207.8 64.8,207.9 65.7,207.9 65.7,207.9 66.6,207.9 66.6,207.1 67.5,207.1 67.5,207.8 68.4,207.8 68.4,207.5 69.3,207.5 69.3,207.8 70.2,207.8 70.2,207.9 71.2,207.9 71.2,207.9 72.1,207.9 72.1,207.3 73.0,207.3 73.0,207.7 73.9,207.7 73.9,207.6 74.8,207.6 74.8,207.7 75.7,207.7 75.7,208.1 76.6,208.1 76.6,207.8 77.5,207.8 77.5,207.1 78.4,207.1 78.4,207.9 79.3,207.9 79.3,207.1 80.2,207.1 80.2,207.8 81.1,207.8 81.1,207.3 82.0,207.3 82.0,208.1 82.9,208.1 82.9,207.6 83.8,207.6 83.8,207.6 84.7,207.6 84.7,208.1 85.6,208.1 85.6,208.3 86.5,208.3 86.5,207.8 87.4,207.8 87.4,207.7 88.3,207.7 88.3,207.9 89.3,207.9 89.3,207.8 90.2,207.8 90.2,207.5 91.1,207.5 91.1,207.9 92.0,207.9 92.0,207.8 92.9,207.8 92.9,208.0 93.8,208.0 93.8,194.2 94.7,194.2 94.7,194.9 95.6,194.9 95.6,195.2 96.5,195.2 96.5,194.7 97.4,194.7 97.4,195.3 98.3,195.3 98.3,194.2 99.2,194.2 99.2,194.3 100.1,194.3 100.1,195.0 101.0,195.0 101.0,194.7 101.9,194.7 101.9,194.8 102.8,194.8 102.8,195.3 103.7,195.3 103.7,194.2 104.6,194.2 104.6,194.8 105.5,194.8 105.5,194.9 106.4,194.9 106.4,195.3 107.4,195.3 107.4,194.9 108.3,194.9 108.3,195.0 109.2,195.0 109.2,194.9 110.1,194.9 110.1,195.5 111.0,195.5 111.0,194.7 111.9,194.7 111.9,195.0 112.8,195.0 112.8,195.9 113.7,195.9 113.7,195.3 114.6,195.3 114.6,194.2 115.5,194.2 115.5,194.3 116.4,194.3 116.4,194.8 117.3,194.8 117.3,195.2 118.2,195.2 118.2,195.2 119.1,195.2 119.1,195.2 120.0,195.2 120.0,194.2 120.9,194.2 120.9,194.0 121.8,194.0 121.8,194.8 122.7,194.8 122.7,195.0 123.6,195.0 123.6,195.5 124.6,195.5 124.6,194.2 125.5,194.2 125.5,194.6 126.4,194.6 126.4,195.1 127.3,195.1 127.3,194.8 128.2,194.8 128.2,195.1 129.1,195.1 129.1,193.1 130.0,193.1 130.0,194.6 130.9,194.6 130.9,194.8 131.8,194.8 131.8,194.5 132.7,194.5 132.7,194.2 133.6,194.2 133.6,194.3 134.5,194.3 134.5,194.7 135.4,194.7 135.4,194.7 136.3,194.7 136.3,194.4 137.2,194.4 137.2,195.0 138.1,195.0 138.1,194.3 139.0,194.3 139.0,194.3 139.9,194.3 139.9,141.4 140.8,141.4 140.8,141.1 141.7,141.1 141.7,140.4 142.7,140.4 142.7,140.1 143.6,140.1 143.6,141.2 144.5,141.2 144.5,140.7 145.4,140.7 145.4,140.5 146.3,140.5 146.3,141.1 147.2,141.1 147.2,141.2 148.1,141.2 148.1,141.4 149.0,141.4 149.0,140.3 149.9,140.3 149.9,141.3 150.8,141.3 150.8,140.5 151.7,140.5 151.7,141.2 152.6,141.2 152.6,140.0 153.5,140.0 153.5,141.3 154.4,141.3 154.4,140.0 155.3,140.0 155.3,141.2 156.2,141.2 156.2,141.1 157.1,141.1 157.1,140.1 158.0,140.1 158.0,140.6 158.9,140.6 158.9,140.5 159.8,140.5 159.8,141.7 160.8,141.7 160.8,141.1 161.7,141.1 161.7,140.5 162.6,140.5 162.6,141.3 163.5,141.3 163.5,140.1 164.4,140.1 164.4,140.6 165.3,140.6 165.3,140.1 166.2,140.1 166.2,140.0 167.1,140.0 167.1,139.4 168.0,139.4 168.0,141.0 168.9,141.0 168.9,139.4 169.8,139.4 169.8,140.9 170.7,140.9 170.7,140.8 171.6,140.8 171.6,140.5 172.5,140.5 172.5,140.8 173.4,140.8 173.4,140.1 174.3,140.1 174.3,139.7 175.2,139.7 175.2,139.3 176.1,139.3 176.1,139.5 177.0,139.5 177.0,140.0 177.9,140.0 177.9,139.7 178.9,139.7 178.9,140.0 179.8,140.0 179.8,140.1 180.7,140.1 180.7,140.1 181.6,140.1 181.6,139.6 182.5,139.6 182.5,140.5 183.4,140.5 183.4,139.9 184.3,139.9 184.3,140.5 185.2,140.5 185.2,140.1 186.1,140.1 186.1,139.8 187.0,139.8 187.0,139.2 187.9,139.2 187.9,139.7 188.8,139.7 188.8,139.7 189.7,139.7 189.7,139.8 190.6,139.8 190.6,138.4 191.5,138.4 191.5,138.8 192.4,138.8 192.4,138.7 193.3,138.7 193.3,139.2 194.2,139.2 194.2,140.0 195.1,140.0 195.1,139.7 196.1,139.7 196.1,139.7 197.0,139.7 197.0,139.1 197.9,139.1 197.9,139.3 198.8,139.3 198.8,138.8 199.7,138.8 199.7,138.5 200.6,138.5 200.6,140.2 201.5,140.2 201.5,139.8 202.4,139.8 202.4,139.3 203.3,139.3 203.3,139.6 204.2,139.6 204.2,138.5 205.1,138.5 205.1,139.1 206.0,139.1 206.0,139.6 206.9,139.6 206.9,139.4 207.8,139.4 207.8,140.2 208.7,140.2 208.7,138.5 209.6,138.5 209.6,139.2 210.5,139.2 210.5,139.7 211.4,139.7 211.4,139.0 212.3,139.0 212.3,139.8 213.2,139.8 213.2,138.5 214.2,138.5 214.2,140.1 215.1,140.1 215.1,139.3 216.0,139.3 216.0,139.6 216.9,139.6 216.9,138.7 217.8,138.7 217.8,139.5 218.7,139.5 218.7,138.1 219.6,138.1 219.6,139.3 220.5,139.3 220.5,138.9 221.4,138.9 221.4,139.5 222.3,139.5 222.3,139.6 223.2,139.6 223.2,139.3 224.1,139.3 224.1,140.2 225.0,140.2 225.0,140.7 225.9,140.7 225.9,140.4 226.8,140.4 226.8,138.7 227.7,138.7 227.7,138.9 228.6,138.9 228.6,139.0 229.5,139.0 229.5,139.2 230.4,139.2 230.4,139.7 231.3,139.7 231.3,139.1 232.3,139.1 232.3,139.6 233.2,139.6 233.2,139.5 234.1,139.5 234.1,140.1 235.0,140.1 235.0,138.7 235.9Line truncated
<circle class="nj-charts-json-dot" cx="93.8" cy="194.2" r="3.5"><title>#5234: 1.22&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="93.8" y1="54.0" x2="93.8" y2="189.2"/>
<text class="nj-charts-note" x="93.8" y="50.0" text-anchor="middle">#5234</text>
<circle class="nj-charts-json-dot" cx="139.9" cy="141.4" r="3.5"><title>#5283: 2.6&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="139.9" y1="54.0" x2="139.9" y2="136.4"/>
<text class="nj-charts-note" x="139.9" y="50.0" text-anchor="middle">#5283</text>
<circle class="nj-charts-json-dot" cx="243.1" cy="133.1" r="3.5"><title>#5592: 2.9&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="243.1" y1="54.0" x2="243.1" y2="128.1"/>
<text class="nj-charts-note" x="243.1" y="50.0" text-anchor="middle">#5592</text>
<circle class="nj-charts-json-dot" cx="265.7" cy="116.2" r="3.5"><title>#5809: 3.7&#215;</title></circle>
<circle class="nj-charts-json-dot" cx="266.6" cy="110.0" r="3.5"><title>#5810: 4.0&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="266.6" y1="41.0" x2="266.6" y2="105.0"/>
<text class="nj-charts-note" x="266.6" y="37.0" text-anchor="middle">#5809, #5810</text>
<circle class="nj-charts-json-dot" cx="299.2" cy="96.1" r="3.5"><title>#5853: 4.9&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="299.2" y1="54.0" x2="299.2" y2="91.1"/>
<text class="nj-charts-note" x="299.2" y="50.0" text-anchor="middle">#5853</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,27 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-dump_canada nj-blog-tl-dump_canada-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-dump_canada">dump() canada.json: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-dump_canada-d">dump() canada.json: speedup over 3.12.0 at each of 317 commits, ending at 3.3x. Labeled steps: #5285, #5634.</desc>
<text class="nj-charts-panel" x="8" y="18">dump() canada.json</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="159.333" x2="330" y2="159.333"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="163.333">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="110.667" x2="330" y2="110.667"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="114.667">4&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">8&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,208.0 45.8,208.0 45.8,207.2 46.7,207.2 46.7,207.9 47.6,207.9 47.6,206.7 48.5,206.7 48.5,207.5 49.4,207.5 49.4,207.7 50.3,207.7 50.3,207.3 51.2,207.3 51.2,207.9 52.1,207.9 52.1,206.5 53.1,206.5 53.1,207.5 54.0,207.5 54.0,208.0 54.9,208.0 54.9,207.6 55.8,207.6 55.8,207.2 56.7,207.2 56.7,207.5 57.6,207.5 57.6,206.6 58.5,206.6 58.5,207.1 59.4,207.1 59.4,207.1 60.3,207.1 60.3,207.2 61.2,207.2 61.2,206.6 62.1,206.6 62.1,207.5 63.0,207.5 63.0,207.6 63.9,207.6 63.9,207.7 64.8,207.7 64.8,207.2 65.7,207.2 65.7,206.5 66.6,206.5 66.6,206.8 67.5,206.8 67.5,207.1 68.4,207.1 68.4,207.0 69.3,207.0 69.3,207.0 70.2,207.0 70.2,206.7 71.2,206.7 71.2,208.2 72.1,208.2 72.1,207.5 73.0,207.5 73.0,206.5 73.9,206.5 73.9,206.7 74.8,206.7 74.8,206.2 75.7,206.2 75.7,208.4 76.6,208.4 76.6,207.3 77.5,207.3 77.5,206.8 78.4,206.8 78.4,208.0 79.3,208.0 79.3,207.7 80.2,207.7 80.2,207.1 81.1,207.1 81.1,207.5 82.0,207.5 82.0,207.9 82.9,207.9 82.9,206.3 83.8,206.3 83.8,206.7 84.7,206.7 84.7,207.5 85.6,207.5 85.6,208.1 86.5,208.1 86.5,206.6 87.4,206.6 87.4,207.1 88.3,207.1 88.3,207.2 89.3,207.2 89.3,207.4 90.2,207.4 90.2,207.0 91.1,207.0 91.1,206.7 92.0,206.7 92.0,206.5 92.9,206.5 92.9,207.6 93.8,207.6 93.8,207.4 94.7,207.4 94.7,207.2 95.6,207.2 95.6,207.5 96.5,207.5 96.5,207.6 97.4,207.6 97.4,208.0 98.3,208.0 98.3,208.2 99.2,208.2 99.2,206.7 100.1,206.7 100.1,207.4 101.0,207.4 101.0,206.6 101.9,206.6 101.9,206.5 102.8,206.5 102.8,208.0 103.7,208.0 103.7,208.0 104.6,208.0 104.6,206.3 105.5,206.3 105.5,208.4 106.4,208.4 106.4,207.8 107.4,207.8 107.4,207.4 108.3,207.4 108.3,206.3 109.2,206.3 109.2,208.1 110.1,208.1 110.1,207.5 111.0,207.5 111.0,207.4 111.9,207.4 111.9,207.5 112.8,207.5 112.8,207.7 113.7,207.7 113.7,208.0 114.6,208.0 114.6,206.9 115.5,206.9 115.5,207.4 116.4,207.4 116.4,207.2 117.3,207.2 117.3,207.7 118.2,207.7 118.2,207.3 119.1,207.3 119.1,208.0 120.0,208.0 120.0,206.7 120.9,206.7 120.9,206.5 121.8,206.5 121.8,207.2 122.7,207.2 122.7,208.1 123.6,208.1 123.6,208.1 124.6,208.1 124.6,206.7 125.5,206.7 125.5,207.8 126.4,207.8 126.4,207.6 127.3,207.6 127.3,207.4 128.2,207.4 128.2,207.0 129.1,207.0 129.1,207.4 130.0,207.4 130.0,208.8 130.9,208.8 130.9,209.2 131.8,209.2 131.8,208.4 132.7,208.4 132.7,208.3 133.6,208.3 133.6,208.0 134.5,208.0 134.5,209.1 135.4,209.1 135.4,208.5 136.3,208.5 136.3,209.1 137.2,209.1 137.2,209.2 138.1,209.2 138.1,208.7 139.0,208.7 139.0,207.7 139.9,207.7 139.9,207.7 140.8,207.7 140.8,207.5 141.7,207.5 141.7,202.0 142.7,202.0 142.7,202.1 143.6,202.1 143.6,201.5 144.5,201.5 144.5,202.2 145.4,202.2 145.4,201.7 146.3,201.7 146.3,201.0 147.2,201.0 147.2,202.0 148.1,202.0 148.1,202.4 149.0,202.4 149.0,201.3 149.9,201.3 149.9,202.1 150.8,202.1 150.8,202.1 151.7,202.1 151.7,201.5 152.6,201.5 152.6,201.1 153.5,201.1 153.5,202.3 154.4,202.3 154.4,201.0 155.3,201.0 155.3,202.8 156.2,202.8 156.2,202.1 157.1,202.1 157.1,201.5 158.0,201.5 158.0,201.6 158.9,201.6 158.9,201.4 159.8,201.4 159.8,202.9 160.8,202.9 160.8,202.5 161.7,202.5 161.7,202.2 162.6,202.2 162.6,202.6 163.5,202.6 163.5,201.9 164.4,201.9 164.4,202.9 165.3,202.9 165.3,202.1 166.2,202.1 166.2,202.2 167.1,202.2 167.1,201.6 168.0,201.6 168.0,202.9 168.9,202.9 168.9,201.6 169.8,201.6 169.8,202.5 170.7,202.5 170.7,202.4 171.6,202.4 171.6,202.8 172.5,202.8 172.5,202.1 173.4,202.1 173.4,202.1 174.3,202.1 174.3,201.4 175.2,201.4 175.2,201.3 176.1,201.3 176.1,202.2 177.0,202.2 177.0,201.5 177.9,201.5 177.9,201.0 178.9,201.0 178.9,202.1 179.8,202.1 179.8,201.4 180.7,201.4 180.7,201.4 181.6,201.4 181.6,201.7 182.5,201.7 182.5,201.9 183.4,201.9 183.4,201.5 184.3,201.5 184.3,201.2 185.2,201.2 185.2,202.1 186.1,202.1 186.1,202.6 187.0,202.6 187.0,202.2 187.9,202.2 187.9,201.5 188.8,201.5 188.8,201.5 189.7,201.5 189.7,202.2 190.6,202.2 190.6,201.5 191.5,201.5 191.5,201.5 192.4,201.5 192.4,202.1 193.3,202.1 193.3,202.0 194.2,202.0 194.2,202.3 195.1,202.3 195.1,201.6 196.1,201.6 196.1,201.9 197.0,201.9 197.0,201.4 197.9,201.4 197.9,202.1 198.8,202.1 198.8,201.7 199.7,201.7 199.7,201.7 200.6,201.7 200.6,202.4 201.5,202.4 201.5,201.4 202.4,201.4 202.4,201.9 203.3,201.9 203.3,202.2 204.2,202.2 204.2,201.6 205.1,201.6 205.1,201.3 206.0,201.3 206.0,202.2 206.9,202.2 206.9,202.0 207.8,202.0 207.8,202.8 208.7,202.8 208.7,201.1 209.6,201.1 209.6,202.0 210.5,202.0 210.5,203.5 211.4,203.5 211.4,201.7 212.3,201.7 212.3,202.3 213.2,202.3 213.2,201.5 214.2,201.5 214.2,202.6 215.1,202.6 215.1,202.2 216.0,202.2 216.0,202.3 216.9,202.3 216.9,202.0 217.8,202.0 217.8,203.3 218.7,203.3 218.7,201.9 219.6,201.9 219.6,202.1 220.5,202.1 220.5,201.7 221.4,201.7 221.4,202.1 222.3,202.1 222.3,201.6 223.2,201.6 223.2,202.3 224.1,202.3 224.1,202.2 225.0,202.2 225.0,202.7 225.9,202.7 225.9,202.8 226.8,202.8 226.8,202.0 227.7,202.0 227.7,202.2 228.6,202.2 228.6,202.1 229.5,202.1 229.5,202.6 230.4,202.6 230.4,202.3 231.3,202.3 231.3,202.3 232.3,202.3 232.3,201.3 233.2,201.3 233.2,203.0 234.1,203.0 234.1,203.0 235.0,203.0 235.0,201.3 235.9Line truncated
<circle class="nj-charts-json-dot" cx="141.7" cy="202.0" r="3.5"><title>#5285: 1.09&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="141.7" y1="54.0" x2="141.7" y2="197.0"/>
<text class="nj-charts-note" x="141.7" y="50.0" text-anchor="middle">#5285</text>
<circle class="nj-charts-json-dot" cx="269.4" cy="128.5" r="3.5"><title>#5634: 3.1&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="269.4" y1="54.0" x2="269.4" y2="123.5"/>
<text class="nj-charts-note" x="269.4" y="50.0" text-anchor="middle">#5634</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

@@ -0,0 +1,35 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-dump_twitter nj-blog-tl-dump_twitter-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-dump_twitter">dump() twitter.json: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-dump_twitter-d">dump() twitter.json: speedup over 3.12.0 at each of 317 commits, ending at 6.7x. Labeled steps: #5285, #5738, #5878, #5883.</desc>
<text class="nj-charts-panel" x="8" y="18">dump() twitter.json</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="171.5" x2="330" y2="171.5"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="175.5">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="135" x2="330" y2="135"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="139">4&#215;</text>
<line class="nj-charts-grid" x1="44" y1="98.5" x2="330" y2="98.5"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="102.5">8&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">16&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,208.0 45.8,208.0 45.8,207.2 46.7,207.2 46.7,207.9 47.6,207.9 47.6,206.8 48.5,206.8 48.5,208.0 49.4,208.0 49.4,207.4 50.3,207.4 50.3,207.3 51.2,207.3 51.2,208.0 52.1,208.0 52.1,206.8 53.1,206.8 53.1,207.1 54.0,207.1 54.0,208.0 54.9,208.0 54.9,207.2 55.8,207.2 55.8,207.5 56.7,207.5 56.7,206.8 57.6,206.8 57.6,206.8 58.5,206.8 58.5,207.5 59.4,207.5 59.4,207.3 60.3,207.3 60.3,207.8 61.2,207.8 61.2,206.8 62.1,206.8 62.1,207.8 63.0,207.8 63.0,207.3 63.9,207.3 63.9,208.0 64.8,208.0 64.8,207.4 65.7,207.4 65.7,207.3 66.6,207.3 66.6,206.9 67.5,206.9 67.5,207.2 68.4,207.2 68.4,207.4 69.3,207.4 69.3,207.6 70.2,207.6 70.2,207.5 71.2,207.5 71.2,207.6 72.1,207.6 72.1,207.4 73.0,207.4 73.0,207.2 73.9,207.2 73.9,207.1 74.8,207.1 74.8,207.3 75.7,207.3 75.7,207.7 76.6,207.7 76.6,207.8 77.5,207.8 77.5,206.8 78.4,206.8 78.4,207.6 79.3,207.6 79.3,207.0 80.2,207.0 80.2,206.9 81.1,206.9 81.1,207.3 82.0,207.3 82.0,207.5 82.9,207.5 82.9,206.8 83.8,206.8 83.8,207.7 84.7,207.7 84.7,207.4 85.6,207.4 85.6,207.4 86.5,207.4 86.5,207.1 87.4,207.1 87.4,207.3 88.3,207.3 88.3,207.5 89.3,207.5 89.3,207.3 90.2,207.3 90.2,207.3 91.1,207.3 91.1,206.8 92.0,206.8 92.0,207.4 92.9,207.4 92.9,207.9 93.8,207.9 93.8,207.3 94.7,207.3 94.7,206.7 95.6,206.7 95.6,207.6 96.5,207.6 96.5,207.7 97.4,207.7 97.4,208.7 98.3,208.7 98.3,208.6 99.2,208.6 99.2,208.6 100.1,208.6 100.1,209.2 101.0,209.2 101.0,208.5 101.9,208.5 101.9,208.2 102.8,208.2 102.8,209.3 103.7,209.3 103.7,208.4 104.6,208.4 104.6,208.4 105.5,208.4 105.5,209.0 106.4,209.0 106.4,209.1 107.4,209.1 107.4,208.7 108.3,208.7 108.3,208.9 109.2,208.9 109.2,208.7 110.1,208.7 110.1,209.0 111.0,209.0 111.0,208.8 111.9,208.8 111.9,208.7 112.8,208.7 112.8,209.3 113.7,209.3 113.7,208.7 114.6,208.7 114.6,208.5 115.5,208.5 115.5,208.5 116.4,208.5 116.4,208.0 117.3,208.0 117.3,208.9 118.2,208.9 118.2,208.7 119.1,208.7 119.1,209.0 120.0,209.0 120.0,208.1 120.9,208.1 120.9,208.0 121.8,208.0 121.8,208.6 122.7,208.6 122.7,208.5 123.6,208.5 123.6,209.2 124.6,209.2 124.6,208.0 125.5,208.0 125.5,209.1 126.4,209.1 126.4,209.0 127.3,209.0 127.3,208.5 128.2,208.5 128.2,209.1 129.1,209.1 129.1,209.0 130.0,209.0 130.0,208.9 130.9,208.9 130.9,208.6 131.8,208.6 131.8,208.7 132.7,208.7 132.7,208.2 133.6,208.2 133.6,209.1 134.5,209.1 134.5,209.3 135.4,209.3 135.4,209.1 136.3,209.1 136.3,209.2 137.2,209.2 137.2,209.3 138.1,209.3 138.1,208.5 139.0,208.5 139.0,208.8 139.9,208.8 139.9,209.5 140.8,209.5 140.8,208.4 141.7,208.4 141.7,145.7 142.7,145.7 142.7,146.6 143.6,146.6 143.6,146.7 144.5,146.7 144.5,145.8 145.4,145.8 145.4,145.8 146.3,145.8 146.3,146.0 147.2,146.0 147.2,146.5 148.1,146.5 148.1,146.5 149.0,146.5 149.0,145.6 149.9,145.6 149.9,146.4 150.8,146.4 150.8,145.5 151.7,145.5 151.7,145.8 152.6,145.8 152.6,145.6 153.5,145.6 153.5,146.7 154.4,146.7 154.4,145.7 155.3,145.7 155.3,146.6 156.2,146.6 156.2,146.8 157.1,146.8 157.1,146.0 158.0,146.0 158.0,146.1 158.9,146.1 158.9,146.4 159.8,146.4 159.8,146.9 160.8,146.9 160.8,146.3 161.7,146.3 161.7,146.4 162.6,146.4 162.6,146.5 163.5,146.5 163.5,146.6 164.4,146.6 164.4,147.3 165.3,147.3 165.3,147.0 166.2,147.0 166.2,146.5 167.1,146.5 167.1,146.4 168.0,146.4 168.0,147.3 168.9,147.3 168.9,146.0 169.8,146.0 169.8,147.5 170.7,147.5 170.7,147.4 171.6,147.4 171.6,147.1 172.5,147.1 172.5,146.4 173.4,146.4 173.4,147.0 174.3,147.0 174.3,146.0 175.2,146.0 175.2,146.2 176.1,146.2 176.1,146.0 177.0,146.0 177.0,146.6 177.9,146.6 177.9,146.4 178.9,146.4 178.9,146.5 179.8,146.5 179.8,146.7 180.7,146.7 180.7,146.6 181.6,146.6 181.6,146.4 182.5,146.4 182.5,147.3 183.4,147.3 183.4,146.1 184.3,146.1 184.3,147.2 185.2,147.2 185.2,146.6 186.1,146.6 186.1,146.3 187.0,146.3 187.0,146.1 187.9,146.1 187.9,146.3 188.8,146.3 188.8,146.0 189.7,146.0 189.7,146.5 190.6,146.5 190.6,145.3 191.5,145.3 191.5,146.2 192.4,146.2 192.4,146.2 193.3,146.2 193.3,146.2 194.2,146.2 194.2,146.0 195.1,146.0 195.1,146.3 196.1,146.3 196.1,145.7 197.0,145.7 197.0,145.8 197.9,145.8 197.9,145.8 198.8,145.8 198.8,145.3 199.7,145.3 199.7,145.3 200.6,145.3 200.6,146.6 201.5,146.6 201.5,146.0 202.4,146.0 202.4,146.3 203.3,146.3 203.3,146.5 204.2,146.5 204.2,146.0 205.1,146.0 205.1,146.1 206.0,146.1 206.0,146.6 206.9,146.6 206.9,146.6 207.8,146.6 207.8,146.8 208.7,146.8 208.7,146.4 209.6,146.4 209.6,146.2 210.5,146.2 210.5,146.5 211.4,146.5 211.4,145.8 212.3,145.8 212.3,146.4 213.2,146.4 213.2,145.9 214.2,145.9 214.2,146.7 215.1,146.7 215.1,146.5 216.0,146.5 216.0,146.6 216.9,146.6 216.9,147.0 217.8,147.0 217.8,147.7 218.7,147.7 218.7,147.0 219.6,147.0 219.6,147.8 220.5,147.8 220.5,146.5 221.4,146.5 221.4,146.8 222.3,146.8 222.3,147.4 223.2,147.4 223.2,147.1 224.1,147.1 224.1,147.5 225.0,147.5 225.0,147.7 225.9,147.7 225.9,147.5 226.8,147.5 226.8,146.9 227.7,146.9 227.7,147.2 228.6,147.2 228.6,146.9 229.5,146.9 229.5,147.2 230.4,147.2 230.4,147.3 231.3,147.3 231.3,147.3 232.3,147.3 232.3,146.8 233.2,146.8 233.2,147.5 234.1,147.5 234.1,147.5 235.0,147.5 235.0,146.6 235.9Line truncated
<circle class="nj-charts-json-dot" cx="141.7" cy="145.7" r="3.5"><title>#5285: 3.3&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="141.7" y1="54.0" x2="141.7" y2="140.7"/>
<text class="nj-charts-note" x="141.7" y="50.0" text-anchor="middle">#5285</text>
<circle class="nj-charts-json-dot" cx="268.5" cy="137.1" r="3.5"><title>#5738: 3.8&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="268.5" y1="54.0" x2="268.5" y2="132.1"/>
<text class="nj-charts-note" x="268.5" y="50.0" text-anchor="middle">#5738</text>
<circle class="nj-charts-json-dot" cx="301.9" cy="128.8" r="3.5"><title>#5878: 4.5&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="301.9" y1="41.0" x2="301.9" y2="123.8"/>
<text class="nj-charts-note" x="301.9" y="37.0" text-anchor="middle">#5878</text>
<circle class="nj-charts-json-dot" cx="308.3" cy="106.8" r="3.5"><title>#5883: 6.8&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="308.3" y1="28.0" x2="308.3" y2="101.8"/>
<text class="nj-charts-note" x="308.3" y="24.0" text-anchor="middle">#5883</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,31 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-from_cbor_twitter nj-blog-tl-from_cbor_twitter-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-from_cbor_twitter">from_cbor() twitter: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-from_cbor_twitter-d">from_cbor() twitter: speedup over 3.12.0 at each of 317 commits, ending at 2.6x. Labeled steps: #5233, #5501, #5185, #5746.</desc>
<text class="nj-charts-panel" x="8" y="18">from_cbor() twitter</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="135" x2="330" y2="135"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="139">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">4&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,209.1 45.8,209.1 45.8,208.2 46.7,208.2 46.7,208.6 47.6,208.6 47.6,208.0 48.5,208.0 48.5,208.5 49.4,208.5 49.4,208.6 50.3,208.6 50.3,208.3 51.2,208.3 51.2,209.1 52.1,209.1 52.1,207.8 53.1,207.8 53.1,208.5 54.0,208.5 54.0,208.6 54.9,208.6 54.9,208.7 55.8,208.7 55.8,207.7 56.7,207.7 56.7,207.1 57.6,207.1 57.6,207.3 58.5,207.3 58.5,206.9 59.4,206.9 59.4,207.1 60.3,207.1 60.3,207.0 61.2,207.0 61.2,207.1 62.1,207.1 62.1,207.1 63.0,207.1 63.0,207.5 63.9,207.5 63.9,207.5 64.8,207.5 64.8,206.8 65.7,206.8 65.7,206.9 66.6,206.9 66.6,206.2 67.5,206.2 67.5,207.1 68.4,207.1 68.4,208.5 69.3,208.5 69.3,208.0 70.2,208.0 70.2,207.7 71.2,207.7 71.2,208.5 72.1,208.5 72.1,207.8 73.0,207.8 73.0,207.0 73.9,207.0 73.9,208.1 74.8,208.1 74.8,208.2 75.7,208.2 75.7,208.7 76.6,208.7 76.6,208.1 77.5,208.1 77.5,207.2 78.4,207.2 78.4,208.3 79.3,208.3 79.3,207.4 80.2,207.4 80.2,207.9 81.1,207.9 81.1,207.7 82.0,207.7 82.0,208.7 82.9,208.7 82.9,207.3 83.8,207.3 83.8,207.9 84.7,207.9 84.7,208.4 85.6,208.4 85.6,208.5 86.5,208.5 86.5,208.0 87.4,208.0 87.4,207.0 88.3,207.0 88.3,208.1 89.3,208.1 89.3,208.1 90.2,208.1 90.2,207.8 91.1,207.8 91.1,207.9 92.0,207.9 92.0,207.9 92.9,207.9 92.9,208.7 93.8,208.7 93.8,208.1 94.7,208.1 94.7,167.8 95.6,167.8 95.6,169.3 96.5,169.3 96.5,168.9 97.4,168.9 97.4,167.9 98.3,167.9 98.3,168.6 99.2,168.6 99.2,168.0 100.1,168.0 100.1,169.0 101.0,169.0 101.0,167.7 101.9,167.7 101.9,166.7 102.8,166.7 102.8,169.3 103.7,169.3 103.7,168.4 104.6,168.4 104.6,168.6 105.5,168.6 105.5,171.9 106.4,171.9 106.4,169.4 107.4,169.4 107.4,169.3 108.3,169.3 108.3,169.1 109.2,169.1 109.2,169.2 110.1,169.2 110.1,169.7 111.0,169.7 111.0,169.4 111.9,169.4 111.9,169.3 112.8,169.3 112.8,170.1 113.7,170.1 113.7,169.2 114.6,169.2 114.6,167.5 115.5,167.5 115.5,167.8 116.4,167.8 116.4,167.7 117.3,167.7 117.3,169.4 118.2,169.4 118.2,168.1 119.1,168.1 119.1,168.7 120.0,168.7 120.0,167.1 120.9,167.1 120.9,167.2 121.8,167.2 121.8,168.8 122.7,168.8 122.7,169.2 123.6,169.2 123.6,169.4 124.6,169.4 124.6,168.1 125.5,168.1 125.5,169.4 126.4,169.4 126.4,169.0 127.3,169.0 127.3,168.9 128.2,168.9 128.2,168.9 129.1,168.9 129.1,168.6 130.0,168.6 130.0,168.9 130.9,168.9 130.9,168.1 131.8,168.1 131.8,168.5 132.7,168.5 132.7,168.9 133.6,168.9 133.6,168.9 134.5,168.9 134.5,169.4 135.4,169.4 135.4,169.7 136.3,169.7 136.3,169.4 137.2,169.4 137.2,169.7 138.1,169.7 138.1,168.1 139.0,168.1 139.0,126.4 139.9,126.4 139.9,118.6 140.8,118.6 140.8,118.0 141.7,118.0 141.7,118.3 142.7,118.3 142.7,118.5 143.6,118.5 143.6,117.8 144.5,117.8 144.5,113.9 145.4,113.9 145.4,114.9 146.3,114.9 146.3,114.8 147.2,114.8 147.2,115.4 148.1,115.4 148.1,115.8 149.0,115.8 149.0,115.5 149.9,115.5 149.9,117.6 150.8,117.6 150.8,116.4 151.7,116.4 151.7,117.1 152.6,117.1 152.6,116.5 153.5,116.5 153.5,118.5 154.4,118.5 154.4,116.0 155.3,116.0 155.3,118.7 156.2,118.7 156.2,117.6 157.1,117.6 157.1,115.9 158.0,115.9 158.0,116.8 158.9,116.8 158.9,116.5 159.8,116.5 159.8,117.7 160.8,117.7 160.8,116.5 161.7,116.5 161.7,116.9 162.6,116.9 162.6,117.3 163.5,117.3 163.5,117.9 164.4,117.9 164.4,118.2 165.3,118.2 165.3,117.1 166.2,117.1 166.2,116.3 167.1,116.3 167.1,115.9 168.0,115.9 168.0,117.7 168.9,117.7 168.9,116.9 169.8,116.9 169.8,117.4 170.7,117.4 170.7,117.2 171.6,117.2 171.6,117.3 172.5,117.3 172.5,116.7 173.4,116.7 173.4,117.0 174.3,117.0 174.3,115.5 175.2,115.5 175.2,148.6 176.1,148.6 176.1,148.9 177.0,148.9 177.0,149.0 177.9,149.0 177.9,149.7 178.9,149.7 178.9,149.8 179.8,149.8 179.8,149.1 180.7,149.1 180.7,150.6 181.6,150.6 181.6,150.2 182.5,150.2 182.5,150.9 183.4,150.9 183.4,149.0 184.3,149.0 184.3,151.3 185.2,151.3 185.2,152.7 186.1,152.7 186.1,151.3 187.0,151.3 187.0,151.3 187.9,151.3 187.9,152.0 188.8,152.0 188.8,150.1 189.7,150.1 189.7,152.3 190.6,152.3 190.6,150.0 191.5,150.0 191.5,151.0 192.4,151.0 192.4,152.0 193.3,152.0 193.3,150.2 194.2,150.2 194.2,151.2 195.1,151.2 195.1,152.1 196.1,152.1 196.1,151.2 197.0,151.2 197.0,150.9 197.9,150.9 197.9,151.2 198.8,151.2 198.8,150.0 199.7,150.0 199.7,151.6 200.6,151.6 200.6,153.1 201.5,153.1 201.5,150.5 202.4,150.5 202.4,151.4 203.3,151.4 203.3,152.4 204.2,152.4 204.2,151.5 205.1,151.5 205.1,151.1 206.0,151.1 206.0,152.5 206.9,152.5 206.9,152.5 207.8,152.5 207.8,152.8 208.7,152.8 208.7,151.0 209.6,151.0 209.6,152.8 210.5,152.8 210.5,152.6 211.4,152.6 211.4,150.3 212.3,150.3 212.3,152.5 213.2,152.5 213.2,151.5 214.2,151.5 214.2,150.7 215.1,150.7 215.1,152.2 216.0,152.2 216.0,152.3 216.9,152.3 216.9,152.4 217.8,152.4 217.8,154.0 218.7,154.0 218.7,151.8 219.6,151.8 219.6,153.9 220.5,153.9 220.5,151.2 221.4,151.2 221.4,152.5 222.3,152.5 222.3,150.7 223.2,150.7 223.2,151.6 224.1,151.6 224.1,151.9 225.0,151.9 225.0,152.1 225.9,152.1 225.9,153.1 226.8,153.1 226.8,151.2 227.7,151.2 227.7,153.9 228.6,153.9 228.6,151.0 229.5,151.0 229.5,151.8 230.4,151.8 230.4,151.7 231.3,151.7 231.3,153.0 232.3,153.0 232.3,151.0 233.2,151.0 233.2,151.5 234.1,151.5 234.1,152.8 235.0,152.8 235.0,119.6 235.9Line truncated
<circle class="nj-charts-json-dot" cx="94.7" cy="167.8" r="3.5"><title>#5233: 1.47&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="94.7" y1="54.0" x2="94.7" y2="162.8"/>
<text class="nj-charts-note" x="94.7" y="50.0" text-anchor="middle">#5233</text>
<circle class="nj-charts-json-dot" cx="139.0" cy="126.4" r="3.5"><title>#5501: 2.2&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="139.0" y1="54.0" x2="139.0" y2="121.4"/>
<text class="nj-charts-note" x="139.0" y="50.0" text-anchor="middle">#5501</text>
<circle class="nj-charts-json-dot" cx="175.2" cy="148.6" r="3.5"><title>#5185: 1.76&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="175.2" y1="41.0" x2="175.2" y2="143.6"/>
<text class="nj-charts-note" x="175.2" y="37.0" text-anchor="middle">#5185</text>
<circle class="nj-charts-json-dot" cx="235.0" cy="119.6" r="3.5"><title>#5746: 2.3&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="235.0" y1="54.0" x2="235.0" y2="114.6"/>
<text class="nj-charts-note" x="235.0" y="50.0" text-anchor="middle">#5746</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

@@ -0,0 +1,37 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-parse_canada nj-blog-tl-parse_canada-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-parse_canada">parse() canada.json: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-parse_canada-d">parse() canada.json: speedup over 3.12.0 at each of 317 commits, ending at 2.8x. Labeled steps: #5234, #5283, #5617, #5738, #5851, #5882.</desc>
<text class="nj-charts-panel" x="8" y="18">parse() canada.json</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="135" x2="330" y2="135"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="139">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">4&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,208.2 45.8,208.2 45.8,208.1 46.7,208.1 46.7,207.7 47.6,207.7 47.6,207.2 48.5,207.2 48.5,208.0 49.4,208.0 49.4,208.2 50.3,208.2 50.3,207.8 51.2,207.8 51.2,208.5 52.1,208.5 52.1,207.3 53.1,207.3 53.1,208.0 54.0,208.0 54.0,209.2 54.9,209.2 54.9,208.5 55.8,208.5 55.8,208.1 56.7,208.1 56.7,207.7 57.6,207.7 57.6,209.8 58.5,209.8 58.5,208.6 59.4,208.6 59.4,208.1 60.3,208.1 60.3,208.1 61.2,208.1 61.2,207.0 62.1,207.0 62.1,207.8 63.0,207.8 63.0,207.6 63.9,207.6 63.9,208.1 64.8,208.1 64.8,208.4 65.7,208.4 65.7,207.7 66.6,207.7 66.6,207.4 67.5,207.4 67.5,208.3 68.4,208.3 68.4,207.3 69.3,207.3 69.3,207.8 70.2,207.8 70.2,207.9 71.2,207.9 71.2,207.9 72.1,207.9 72.1,207.4 73.0,207.4 73.0,207.5 73.9,207.5 73.9,208.1 74.8,208.1 74.8,208.1 75.7,208.1 75.7,207.9 76.6,207.9 76.6,207.8 77.5,207.8 77.5,207.0 78.4,207.0 78.4,207.6 79.3,207.6 79.3,207.8 80.2,207.8 80.2,207.3 81.1,207.3 81.1,207.6 82.0,207.6 82.0,208.6 82.9,208.6 82.9,206.5 83.8,206.5 83.8,208.0 84.7,208.0 84.7,208.7 85.6,208.7 85.6,208.0 86.5,208.0 86.5,207.7 87.4,207.7 87.4,208.4 88.3,208.4 88.3,207.9 89.3,207.9 89.3,207.5 90.2,207.5 90.2,207.9 91.1,207.9 91.1,207.4 92.0,207.4 92.0,207.5 92.9,207.5 92.9,208.5 93.8,208.5 93.8,197.2 94.7,197.2 94.7,197.7 95.6,197.7 95.6,196.5 96.5,196.5 96.5,196.7 97.4,196.7 97.4,197.5 98.3,197.5 98.3,195.7 99.2,195.7 99.2,197.0 100.1,197.0 100.1,197.8 101.0,197.8 101.0,197.1 101.9,197.1 101.9,196.7 102.8,196.7 102.8,197.2 103.7,197.2 103.7,197.0 104.6,197.0 104.6,197.4 105.5,197.4 105.5,197.4 106.4,197.4 106.4,197.3 107.4,197.3 107.4,196.6 108.3,196.6 108.3,197.6 109.2,197.6 109.2,197.6 110.1,197.6 110.1,197.3 111.0,197.3 111.0,197.3 111.9,197.3 111.9,197.3 112.8,197.3 112.8,197.8 113.7,197.8 113.7,197.7 114.6,197.7 114.6,195.0 115.5,195.0 115.5,196.3 116.4,196.3 116.4,197.6 117.3,197.6 117.3,196.7 118.2,196.7 118.2,196.0 119.1,196.0 119.1,196.5 120.0,196.5 120.0,196.2 120.9,196.2 120.9,196.3 121.8,196.3 121.8,197.4 122.7,197.4 122.7,197.3 123.6,197.3 123.6,197.8 124.6,197.8 124.6,195.5 125.5,195.5 125.5,197.2 126.4,197.2 126.4,197.3 127.3,197.3 127.3,196.4 128.2,196.4 128.2,196.7 129.1,196.7 129.1,197.7 130.0,197.7 130.0,196.7 130.9,196.7 130.9,196.9 131.8,196.9 131.8,196.3 132.7,196.3 132.7,196.7 133.6,196.7 133.6,196.9 134.5,196.9 134.5,197.3 135.4,197.3 135.4,197.5 136.3,197.5 136.3,196.9 137.2,196.9 137.2,197.3 138.1,197.3 138.1,197.0 139.0,197.0 139.0,196.7 139.9,196.7 139.9,167.5 140.8,167.5 140.8,168.6 141.7,168.6 141.7,169.1 142.7,169.1 142.7,167.8 143.6,167.8 143.6,167.2 144.5,167.2 144.5,168.9 145.4,168.9 145.4,167.6 146.3,167.6 146.3,167.2 147.2,167.2 147.2,168.6 148.1,168.6 148.1,169.8 149.0,169.8 149.0,167.0 149.9,167.0 149.9,169.1 150.8,169.1 150.8,168.0 151.7,168.0 151.7,169.0 152.6,169.0 152.6,167.3 153.5,167.3 153.5,168.7 154.4,168.7 154.4,169.0 155.3,169.0 155.3,168.7 156.2,168.7 156.2,168.0 157.1,168.0 157.1,166.0 158.0,166.0 158.0,168.7 158.9,168.7 158.9,167.5 159.8,167.5 159.8,169.2 160.8,169.2 160.8,168.7 161.7,168.7 161.7,167.6 162.6,167.6 162.6,168.2 163.5,168.2 163.5,171.3 164.4,171.3 164.4,170.2 165.3,170.2 165.3,168.0 166.2,168.0 166.2,166.7 167.1,166.7 167.1,168.2 168.0,168.2 168.0,168.0 168.9,168.0 168.9,167.4 169.8,167.4 169.8,167.6 170.7,167.6 170.7,167.5 171.6,167.5 171.6,167.9 172.5,167.9 172.5,167.4 173.4,167.4 173.4,169.8 174.3,169.8 174.3,168.8 175.2,168.8 175.2,166.9 176.1,166.9 176.1,167.7 177.0,167.7 177.0,167.4 177.9,167.4 177.9,167.3 178.9,167.3 178.9,168.8 179.8,168.8 179.8,168.0 180.7,168.0 180.7,167.4 181.6,167.4 181.6,167.5 182.5,167.5 182.5,168.3 183.4,168.3 183.4,168.0 184.3,168.0 184.3,169.1 185.2,169.1 185.2,177.1 186.1,177.1 186.1,176.5 187.0,176.5 187.0,166.6 187.9,166.6 187.9,167.4 188.8,167.4 188.8,167.6 189.7,167.6 189.7,167.4 190.6,167.4 190.6,167.7 191.5,167.7 191.5,166.9 192.4,166.9 192.4,167.1 193.3,167.1 193.3,166.5 194.2,166.5 194.2,166.3 195.1,166.3 195.1,167.0 196.1,167.0 196.1,167.2 197.0,167.2 197.0,167.0 197.9,167.0 197.9,167.0 198.8,167.0 198.8,166.4 199.7,166.4 199.7,165.4 200.6,165.4 200.6,168.1 201.5,168.1 201.5,167.5 202.4,167.5 202.4,167.3 203.3,167.3 203.3,167.0 204.2,167.0 204.2,166.2 205.1,166.2 205.1,166.8 206.0,166.8 206.0,167.1 206.9,167.1 206.9,167.4 207.8,167.4 207.8,167.9 208.7,167.9 208.7,165.4 209.6,165.4 209.6,168.3 210.5,168.3 210.5,168.2 211.4,168.2 211.4,166.1 212.3,166.1 212.3,167.4 213.2,167.4 213.2,166.0 214.2,166.0 214.2,168.3 215.1,168.3 215.1,167.8 216.0,167.8 216.0,166.3 216.9,166.3 216.9,167.3 217.8,167.3 217.8,167.3 218.7,167.3 218.7,165.8 219.6,165.8 219.6,167.6 220.5,167.6 220.5,164.5 221.4,164.5 221.4,165.8 222.3,165.8 222.3,165.4 223.2,165.4 223.2,166.3 224.1,166.3 224.1,166.5 225.0,166.5 225.0,166.0 225.9,166.0 225.9,166.2 226.8,166.2 226.8,165.4 227.7,165.4 227.7,165.0 228.6,165.0 228.6,167.3 229.5,167.3 229.5,166.0 230.4,166.0 230.4,165.5 231.3,165.5 231.3,165.3 232.3,165.3 232.3,164.9 233.2,164.9 233.2,166.2 234.1,166.2 234.1,166.1 235.0,166.1 235.0,166.1 235.9Line truncated
<circle class="nj-charts-json-dot" cx="93.8" cy="197.2" r="3.5"><title>#5234: 1.11&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="93.8" y1="54.0" x2="93.8" y2="192.2"/>
<text class="nj-charts-note" x="93.8" y="50.0" text-anchor="middle">#5234</text>
<circle class="nj-charts-json-dot" cx="139.9" cy="167.5" r="3.5"><title>#5283: 1.47&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="139.9" y1="54.0" x2="139.9" y2="162.5"/>
<text class="nj-charts-note" x="139.9" y="50.0" text-anchor="middle">#5283</text>
<circle class="nj-charts-json-dot" cx="187.0" cy="166.6" r="3.5"><title>#5617: 1.48&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="187.0" y1="54.0" x2="187.0" y2="161.6"/>
<text class="nj-charts-note" x="187.0" y="50.0" text-anchor="middle">#5617</text>
<circle class="nj-charts-json-dot" cx="268.5" cy="137.9" r="3.5"><title>#5738: 1.95&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="268.5" y1="54.0" x2="268.5" y2="132.9"/>
<text class="nj-charts-note" x="268.5" y="50.0" text-anchor="middle">#5738</text>
<circle class="nj-charts-json-dot" cx="297.4" cy="125.1" r="3.5"><title>#5851: 2.2&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="297.4" y1="41.0" x2="297.4" y2="120.1"/>
<text class="nj-charts-note" x="297.4" y="37.0" text-anchor="middle">#5851</text>
<circle class="nj-charts-json-dot" cx="312.8" cy="99.2" r="3.5"><title>#5882: 2.8&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="312.8" y1="54.0" x2="312.8" y2="94.2"/>
<text class="nj-charts-note" x="312.0" y="50.0" text-anchor="middle">#5882</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,37 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-parse_citm nj-blog-tl-parse_citm-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-parse_citm">parse() citm_catalog.json: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-parse_citm-d">parse() citm_catalog.json: speedup over 3.12.0 at each of 317 commits, ending at 3.3x. Labeled steps: #5234, #5283, #5592, #5809, #5810, #5882.</desc>
<text class="nj-charts-panel" x="8" y="18">parse() citm_catalog.json</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="159.333" x2="330" y2="159.333"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="163.333">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="110.667" x2="330" y2="110.667"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="114.667">4&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">8&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,208.2 45.8,208.2 45.8,207.8 46.7,207.8 46.7,207.5 47.6,207.5 47.6,206.4 48.5,206.4 48.5,208.3 49.4,208.3 49.4,207.3 50.3,207.3 50.3,206.8 51.2,206.8 51.2,207.8 52.1,207.8 52.1,206.8 53.1,206.8 53.1,207.3 54.0,207.3 54.0,207.6 54.9,207.6 54.9,207.8 55.8,207.8 55.8,207.0 56.7,207.0 56.7,207.2 57.6,207.2 57.6,207.2 58.5,207.2 58.5,207.3 59.4,207.3 59.4,207.5 60.3,207.5 60.3,207.4 61.2,207.4 61.2,206.5 62.1,206.5 62.1,207.6 63.0,207.6 63.0,207.6 63.9,207.6 63.9,207.1 64.8,207.1 64.8,207.0 65.7,207.0 65.7,207.6 66.6,207.6 66.6,206.6 67.5,206.6 67.5,207.3 68.4,207.3 68.4,206.8 69.3,206.8 69.3,207.3 70.2,207.3 70.2,207.7 71.2,207.7 71.2,207.9 72.1,207.9 72.1,207.2 73.0,207.2 73.0,206.4 73.9,206.4 73.9,207.6 74.8,207.6 74.8,206.4 75.7,206.4 75.7,208.0 76.6,208.0 76.6,207.4 77.5,207.4 77.5,206.4 78.4,206.4 78.4,207.5 79.3,207.5 79.3,207.1 80.2,207.1 80.2,206.9 81.1,206.9 81.1,207.6 82.0,207.6 82.0,207.6 82.9,207.6 82.9,207.0 83.8,207.0 83.8,206.8 84.7,206.8 84.7,208.0 85.6,208.0 85.6,207.6 86.5,207.6 86.5,206.6 87.4,206.6 87.4,206.7 88.3,206.7 88.3,207.3 89.3,207.3 89.3,206.9 90.2,206.9 90.2,207.6 91.1,207.6 91.1,207.1 92.0,207.1 92.0,207.6 92.9,207.6 92.9,207.9 93.8,207.9 93.8,177.3 94.7,177.3 94.7,176.7 95.6,176.7 95.6,176.9 96.5,176.9 96.5,176.8 97.4,176.8 97.4,176.8 98.3,176.8 98.3,176.2 99.2,176.2 99.2,176.0 100.1,176.0 100.1,176.8 101.0,176.8 101.0,176.7 101.9,176.7 101.9,175.9 102.8,175.9 102.8,177.0 103.7,177.0 103.7,176.1 104.6,176.1 104.6,175.9 105.5,175.9 105.5,177.2 106.4,177.2 106.4,177.2 107.4,177.2 107.4,176.7 108.3,176.7 108.3,176.8 109.2,176.8 109.2,176.6 110.1,176.6 110.1,176.8 111.0,176.8 111.0,177.0 111.9,177.0 111.9,176.7 112.8,176.7 112.8,177.1 113.7,177.1 113.7,176.8 114.6,176.8 114.6,175.0 115.5,175.0 115.5,176.6 116.4,176.6 116.4,176.7 117.3,176.7 117.3,176.8 118.2,176.8 118.2,176.0 119.1,176.0 119.1,176.6 120.0,176.6 120.0,176.5 120.9,176.5 120.9,176.5 121.8,176.5 121.8,176.0 122.7,176.0 122.7,177.1 123.6,177.1 123.6,176.4 124.6,176.4 124.6,175.7 125.5,175.7 125.5,176.6 126.4,176.6 126.4,176.6 127.3,176.6 127.3,176.6 128.2,176.6 128.2,176.6 129.1,176.6 129.1,176.2 130.0,176.2 130.0,176.9 130.9,176.9 130.9,175.3 131.8,175.3 131.8,176.1 132.7,176.1 132.7,176.6 133.6,176.6 133.6,176.9 134.5,176.9 134.5,176.9 135.4,176.9 135.4,177.0 136.3,177.0 136.3,176.4 137.2,176.4 137.2,176.6 138.1,176.6 138.1,176.6 139.0,176.6 139.0,176.3 139.9,176.3 139.9,161.2 140.8,161.2 140.8,160.9 141.7,160.9 141.7,160.4 142.7,160.4 142.7,160.9 143.6,160.9 143.6,159.8 144.5,159.8 144.5,159.4 145.4,159.4 145.4,158.0 146.3,158.0 146.3,158.9 147.2,158.9 147.2,159.0 148.1,159.0 148.1,159.3 149.0,159.3 149.0,158.1 149.9,158.1 149.9,159.1 150.8,159.1 150.8,158.2 151.7,158.2 151.7,158.6 152.6,158.6 152.6,158.5 153.5,158.5 153.5,158.8 154.4,158.8 154.4,158.3 155.3,158.3 155.3,159.4 156.2,159.4 156.2,158.8 157.1,158.8 157.1,157.7 158.0,157.7 158.0,158.4 158.9,158.4 158.9,158.5 159.8,158.5 159.8,159.2 160.8,159.2 160.8,158.9 161.7,158.9 161.7,158.6 162.6,158.6 162.6,159.1 163.5,159.1 163.5,159.2 164.4,159.2 164.4,159.2 165.3,159.2 165.3,158.3 166.2,158.3 166.2,158.2 167.1,158.2 167.1,158.7 168.0,158.7 168.0,158.9 168.9,158.9 168.9,158.7 169.8,158.7 169.8,159.2 170.7,159.2 170.7,158.5 171.6,158.5 171.6,158.9 172.5,158.9 172.5,158.7 173.4,158.7 173.4,159.5 174.3,159.5 174.3,157.8 175.2,157.8 175.2,158.3 176.1,158.3 176.1,157.8 177.0,157.8 177.0,158.6 177.9,158.6 177.9,158.0 178.9,158.0 178.9,158.3 179.8,158.3 179.8,158.1 180.7,158.1 180.7,158.7 181.6,158.7 181.6,157.7 182.5,157.7 182.5,158.0 183.4,158.0 183.4,158.9 184.3,158.9 184.3,160.0 185.2,160.0 185.2,160.4 186.1,160.4 186.1,160.3 187.0,160.3 187.0,158.9 187.9,158.9 187.9,159.7 188.8,159.7 188.8,159.9 189.7,159.9 189.7,160.4 190.6,160.4 190.6,159.8 191.5,159.8 191.5,159.1 192.4,159.1 192.4,160.3 193.3,160.3 193.3,159.3 194.2,159.3 194.2,160.1 195.1,160.1 195.1,160.0 196.1,160.0 196.1,160.0 197.0,160.0 197.0,160.4 197.9,160.4 197.9,159.9 198.8,159.9 198.8,158.7 199.7,158.7 199.7,159.6 200.6,159.6 200.6,160.2 201.5,160.2 201.5,159.3 202.4,159.3 202.4,160.6 203.3,160.6 203.3,160.1 204.2,160.1 204.2,158.7 205.1,158.7 205.1,159.2 206.0,159.2 206.0,160.7 206.9,160.7 206.9,160.2 207.8,160.2 207.8,160.7 208.7,160.7 208.7,160.0 209.6,160.0 209.6,161.1 210.5,161.1 210.5,160.8 211.4,160.8 211.4,159.5 212.3,159.5 212.3,160.2 213.2,160.2 213.2,160.1 214.2,160.1 214.2,161.0 215.1,161.0 215.1,160.1 216.0,160.1 216.0,160.1 216.9,160.1 216.9,160.5 217.8,160.5 217.8,159.4 218.7,159.4 218.7,159.2 219.6,159.2 219.6,159.1 220.5,159.1 220.5,157.9 221.4,157.9 221.4,158.1 222.3,158.1 222.3,159.0 223.2,159.0 223.2,158.7 224.1,158.7 224.1,159.0 225.0,159.0 225.0,159.1 225.9,159.1 225.9,159.5 226.8,159.5 226.8,158.5 227.7,158.5 227.7,158.0 228.6,158.0 228.6,159.2 229.5,159.2 229.5,158.8 230.4,158.8 230.4,159.4 231.3,159.4 231.3,159.3 232.3,159.3 232.3,158.1 233.2,158.1 233.2,159.7 234.1,159.7 234.1,160.0 235.0,160.0 235.0,159.7 235.9Line truncated
<circle class="nj-charts-json-dot" cx="93.8" cy="177.3" r="3.5"><title>#5234: 1.55&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="93.8" y1="54.0" x2="93.8" y2="172.3"/>
<text class="nj-charts-note" x="93.8" y="50.0" text-anchor="middle">#5234</text>
<circle class="nj-charts-json-dot" cx="139.9" cy="161.2" r="3.5"><title>#5283: 1.95&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="139.9" y1="54.0" x2="139.9" y2="156.2"/>
<text class="nj-charts-note" x="139.9" y="50.0" text-anchor="middle">#5283</text>
<circle class="nj-charts-json-dot" cx="243.1" cy="153.9" r="3.5"><title>#5592: 2.2&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="243.1" y1="54.0" x2="243.1" y2="148.9"/>
<text class="nj-charts-note" x="243.1" y="50.0" text-anchor="middle">#5592</text>
<circle class="nj-charts-json-dot" cx="265.7" cy="145.4" r="3.5"><title>#5809: 2.4&#215;</title></circle>
<circle class="nj-charts-json-dot" cx="266.6" cy="136.3" r="3.5"><title>#5810: 2.8&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="266.6" y1="41.0" x2="266.6" y2="131.3"/>
<text class="nj-charts-note" x="266.6" y="37.0" text-anchor="middle">#5809, #5810</text>
<circle class="nj-charts-json-dot" cx="312.8" cy="123.3" r="3.5"><title>#5882: 3.3&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="312.8" y1="54.0" x2="312.8" y2="118.3"/>
<text class="nj-charts-note" x="312.0" y="50.0" text-anchor="middle">#5882</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,25 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-parse_twitter_ifstream nj-blog-tl-parse_twitter_ifstream-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-parse_twitter_ifstream">parse() twitter.json, std::ifstream: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-parse_twitter_ifstream-d">parse() twitter.json, std::ifstream: speedup over 3.12.0 at each of 317 commits, ending at 2.2x. Labeled steps: #5828, #5884.</desc>
<text class="nj-charts-panel" x="8" y="18">parse() twitter.json, std::ifstream</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="135" x2="330" y2="135"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="139">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">4&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,209.3 45.8,209.3 45.8,206.6 46.7,206.6 46.7,208.4 47.6,208.4 47.6,205.9 48.5,205.9 48.5,209.4 49.4,209.4 49.4,208.3 50.3,208.3 50.3,207.9 51.2,207.9 51.2,209.5 52.1,209.5 52.1,205.7 53.1,205.7 53.1,206.7 54.0,206.7 54.0,209.2 54.9,209.2 54.9,208.2 55.8,208.2 55.8,206.9 56.7,206.9 56.7,207.4 57.6,207.4 57.6,207.4 58.5,207.4 58.5,207.5 59.4,207.5 59.4,206.9 60.3,206.9 60.3,206.9 61.2,206.9 61.2,208.4 62.1,208.4 62.1,208.6 63.0,208.6 63.0,209.2 63.9,209.2 63.9,207.7 64.8,207.7 64.8,207.0 65.7,207.0 65.7,206.7 66.6,206.7 66.6,206.0 67.5,206.0 67.5,207.5 68.4,207.5 68.4,206.3 69.3,206.3 69.3,206.7 70.2,206.7 70.2,206.7 71.2,206.7 71.2,209.3 72.1,209.3 72.1,206.7 73.0,206.7 73.0,206.8 73.9,206.8 73.9,206.6 74.8,206.6 74.8,206.8 75.7,206.8 75.7,209.2 76.6,209.2 76.6,207.6 77.5,207.6 77.5,205.9 78.4,205.9 78.4,209.1 79.3,209.1 79.3,206.6 80.2,206.6 80.2,207.4 81.1,207.4 81.1,206.9 82.0,206.9 82.0,209.1 82.9,209.1 82.9,205.7 83.8,205.7 83.8,206.9 84.7,206.9 84.7,208.0 85.6,208.0 85.6,208.5 86.5,208.5 86.5,206.5 87.4,206.5 87.4,206.0 88.3,206.0 88.3,207.9 89.3,207.9 89.3,206.6 90.2,206.6 90.2,206.5 91.1,206.5 91.1,206.5 92.0,206.5 92.0,207.1 92.9,207.1 92.9,208.0 93.8,208.0 93.8,208.1 94.7,208.1 94.7,206.7 95.6,206.7 95.6,207.8 96.5,207.8 96.5,206.6 97.4,206.6 97.4,208.1 98.3,208.1 98.3,205.9 99.2,205.9 99.2,206.7 100.1,206.7 100.1,208.0 101.0,208.0 101.0,207.3 101.9,207.3 101.9,206.7 102.8,206.7 102.8,209.3 103.7,209.3 103.7,206.5 104.6,206.5 104.6,207.2 105.5,207.2 105.5,208.2 106.4,208.2 106.4,209.3 107.4,209.3 107.4,207.8 108.3,207.8 108.3,206.9 109.2,206.9 109.2,206.7 110.1,206.7 110.1,209.0 111.0,209.0 111.0,208.0 111.9,208.0 111.9,208.1 112.8,208.1 112.8,209.2 113.7,209.2 113.7,208.1 114.6,208.1 114.6,205.5 115.5,205.5 115.5,206.9 116.4,206.9 116.4,206.6 117.3,206.6 117.3,207.8 118.2,207.8 118.2,206.7 119.1,206.7 119.1,206.9 120.0,206.9 120.0,206.7 120.9,206.7 120.9,206.3 121.8,206.3 121.8,207.1 122.7,207.1 122.7,208.6 123.6,208.6 123.6,208.7 124.6,208.7 124.6,206.6 125.5,206.6 125.5,209.3 126.4,209.3 126.4,208.0 127.3,208.0 127.3,206.7 128.2,206.7 128.2,207.7 129.1,207.7 129.1,206.9 130.0,206.9 130.0,208.9 130.9,208.9 130.9,208.7 131.8,208.7 131.8,207.7 132.7,207.7 132.7,208.8 133.6,208.8 133.6,207.8 134.5,207.8 134.5,210.4 135.4,210.4 135.4,209.0 136.3,209.0 136.3,209.0 137.2,209.0 137.2,209.1 138.1,209.1 138.1,208.0 139.0,208.0 139.0,207.7 139.9,207.7 139.9,208.3 140.8,208.3 140.8,207.0 141.7,207.0 141.7,207.2 142.7,207.2 142.7,207.5 143.6,207.5 143.6,208.0 144.5,208.0 144.5,207.6 145.4,207.6 145.4,207.9 146.3,207.9 146.3,207.6 147.2,207.6 147.2,208.5 148.1,208.5 148.1,209.2 149.0,209.2 149.0,206.3 149.9,206.3 149.9,208.8 150.8,208.8 150.8,207.6 151.7,207.6 151.7,207.4 152.6,207.4 152.6,207.5 153.5,207.5 153.5,209.0 154.4,209.0 154.4,206.8 155.3,206.8 155.3,209.3 156.2,209.3 156.2,210.0 157.1,210.0 157.1,207.0 158.0,207.0 158.0,207.3 158.9,207.3 158.9,208.1 159.8,208.1 159.8,209.8 160.8,209.8 160.8,208.1 161.7,208.1 161.7,208.1 162.6,208.1 162.6,208.6 163.5,208.6 163.5,208.2 164.4,208.2 164.4,210.4 165.3,210.4 165.3,207.7 166.2,207.7 166.2,207.2 167.1,207.2 167.1,206.6 168.0,206.6 168.0,210.0 168.9,210.0 168.9,206.5 169.8,206.5 169.8,210.0 170.7,210.0 170.7,208.8 171.6,208.8 171.6,208.8 172.5,208.8 172.5,209.5 173.4,209.5 173.4,208.9 174.3,208.9 174.3,206.3 175.2,206.3 175.2,207.2 176.1,207.2 176.1,206.9 177.0,206.9 177.0,207.2 177.9,207.2 177.9,206.5 178.9,206.5 178.9,207.1 179.8,207.1 179.8,208.0 180.7,208.0 180.7,207.6 181.6,207.6 181.6,207.9 182.5,207.9 182.5,207.5 183.4,207.5 183.4,205.6 184.3,205.6 184.3,208.0 185.2,208.0 185.2,209.7 186.1,209.7 186.1,207.9 187.0,207.9 187.0,207.6 187.9,207.6 187.9,208.5 188.8,208.5 188.8,207.9 189.7,207.9 189.7,210.5 190.6,210.5 190.6,206.7 191.5,206.7 191.5,207.7 192.4,207.7 192.4,209.2 193.3,209.2 193.3,206.7 194.2,206.7 194.2,209.3 195.1,209.3 195.1,208.0 196.1,208.0 196.1,208.0 197.0,208.0 197.0,207.9 197.9,207.9 197.9,208.2 198.8,208.2 198.8,207.9 199.7,207.9 199.7,207.0 200.6,207.0 200.6,208.8 201.5,208.8 201.5,208.0 202.4,208.0 202.4,208.0 203.3,208.0 203.3,209.2 204.2,209.2 204.2,206.7 205.1,206.7 205.1,206.6 206.0,206.6 206.0,208.5 206.9,208.5 206.9,208.9 207.8,208.9 207.8,210.1 208.7,210.1 208.7,206.4 209.6,206.4 209.6,209.4 210.5,209.4 210.5,210.1 211.4,210.1 211.4,207.6 212.3,207.6 212.3,209.5 213.2,209.5 213.2,208.7 214.2,208.7 214.2,211.2 215.1,211.2 215.1,210.1 216.0,210.1 216.0,211.8 216.9,211.8 216.9,208.8 217.8,208.8 217.8,209.2 218.7,209.2 218.7,207.7 219.6,207.7 219.6,208.1 220.5,208.1 220.5,206.3 221.4,206.3 221.4,206.7 222.3,206.7 222.3,207.3 223.2,207.3 223.2,207.8 224.1,207.8 224.1,208.7 225.0,208.7 225.0,210.1 225.9,210.1 225.9,210.1 226.8,210.1 226.8,206.8 227.7,206.8 227.7,209.0 228.6,209.0 228.6,208.7 229.5,208.7 229.5,209.2 230.4,209.2 230.4,208.6 231.3,208.6 231.3,209.0 232.3,209.0 232.3,207.3 233.2,207.3 233.2,209.0 234.1,209.0 234.1,209.3 235.0,209.3 235.0,207.3 235.9Line truncated
<circle class="nj-charts-json-dot" cx="287.5" cy="136.8" r="3.5"><title>#5828: 1.97&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="287.5" y1="54.0" x2="287.5" y2="131.8"/>
<text class="nj-charts-note" x="287.5" y="50.0" text-anchor="middle">#5828</text>
<circle class="nj-charts-json-dot" cx="306.5" cy="124.7" r="3.5"><title>#5884: 2.2&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="306.5" y1="41.0" x2="306.5" y2="119.7"/>
<text class="nj-charts-note" x="306.5" y="37.0" text-anchor="middle">#5884</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

@@ -0,0 +1,30 @@
<svg class="nj-fig nj-charts nj-charts--timeline" viewBox="0 0 340 252" role="img" aria-labelledby="nj-blog-tl-to_cbor_twitter nj-blog-tl-to_cbor_twitter-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-blog-tl-to_cbor_twitter">to_cbor() twitter: speedup over 3.12.0 by commit</title>
<desc id="nj-blog-tl-to_cbor_twitter-d">to_cbor() twitter: speedup over 3.12.0 at each of 317 commits, ending at 5.0x. Labeled steps: #5328, #5824, #5885.</desc>
<text class="nj-charts-panel" x="8" y="18">to_cbor() twitter</text>
<line class="nj-charts-grid" x1="44" y1="208" x2="330" y2="208"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="212">1&#215;</text>
<line class="nj-charts-grid" x1="44" y1="159.333" x2="330" y2="159.333"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="163.333">2&#215;</text>
<line class="nj-charts-grid" x1="44" y1="110.667" x2="330" y2="110.667"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="114.667">4&#215;</text>
<line class="nj-charts-grid" x1="44" y1="62" x2="330" y2="62"/>
<text class="nj-charts-tick nj-charts-tick--r" x="38" y="66">8&#215;</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="44" y2="212"/>
<text class="nj-charts-tick" x="44" y="225">3.12.0</text>
<line class="nj-charts-axis" x1="126.361" y1="208" x2="126.361" y2="212"/>
<text class="nj-charts-tick" x="126.361" y="225">Sep 2026</text>
<line class="nj-charts-axis" x1="215.962" y1="208" x2="215.962" y2="212"/>
<text class="nj-charts-tick" x="215.962" y="225">Oct</text>
<polyline class="nj-charts-json" points="44.0,208.0 44.9,208.0 44.9,208.0 45.8,208.0 45.8,204.8 46.7,204.8 46.7,205.2 47.6,205.2 47.6,204.6 48.5,204.6 48.5,205.2 49.4,205.2 49.4,204.9 50.3,204.9 50.3,204.8 51.2,204.8 51.2,205.0 52.1,205.0 52.1,204.9 53.1,204.9 53.1,205.0 54.0,205.0 54.0,205.3 54.9,205.3 54.9,204.9 55.8,204.9 55.8,205.1 56.7,205.1 56.7,211.7 57.6,211.7 57.6,206.7 58.5,206.7 58.5,204.1 59.4,204.1 59.4,207.6 60.3,207.6 60.3,204.0 61.2,204.0 61.2,203.7 62.1,203.7 62.1,204.0 63.0,204.0 63.0,205.0 63.9,205.0 63.9,204.3 64.8,204.3 64.8,204.2 65.7,204.2 65.7,203.9 66.6,203.9 66.6,202.6 67.5,202.6 67.5,204.1 68.4,204.1 68.4,204.1 69.3,204.1 69.3,204.1 70.2,204.1 70.2,204.3 71.2,204.3 71.2,206.1 72.1,206.1 72.1,204.2 73.0,204.2 73.0,204.0 73.9,204.0 73.9,204.2 74.8,204.2 74.8,204.2 75.7,204.2 75.7,204.2 76.6,204.2 76.6,204.1 77.5,204.1 77.5,204.3 78.4,204.3 78.4,204.7 79.3,204.7 79.3,208.4 80.2,208.4 80.2,203.4 81.1,203.4 81.1,206.1 82.0,206.1 82.0,204.3 82.9,204.3 82.9,203.1 83.8,203.1 83.8,204.0 84.7,204.0 84.7,204.1 85.6,204.1 85.6,203.6 86.5,203.6 86.5,204.1 87.4,204.1 87.4,203.0 88.3,203.0 88.3,204.1 89.3,204.1 89.3,204.3 90.2,204.3 90.2,203.6 91.1,203.6 91.1,204.3 92.0,204.3 92.0,204.6 92.9,204.6 92.9,204.5 93.8,204.5 93.8,208.7 94.7,208.7 94.7,205.1 95.6,205.1 95.6,205.4 96.5,205.4 96.5,205.1 97.4,205.1 97.4,205.2 98.3,205.2 98.3,206.8 99.2,206.8 99.2,204.5 100.1,204.5 100.1,205.4 101.0,205.4 101.0,205.0 101.9,205.0 101.9,204.6 102.8,204.6 102.8,205.6 103.7,205.6 103.7,204.9 104.6,204.9 104.6,204.8 105.5,204.8 105.5,206.4 106.4,206.4 106.4,205.5 107.4,205.5 107.4,204.9 108.3,204.9 108.3,209.3 109.2,209.3 109.2,205.8 110.1,205.8 110.1,206.4 111.0,206.4 111.0,205.5 111.9,205.5 111.9,205.2 112.8,205.2 112.8,205.3 113.7,205.3 113.7,205.1 114.6,205.1 114.6,204.3 115.5,204.3 115.5,204.5 116.4,204.5 116.4,204.7 117.3,204.7 117.3,204.0 118.2,204.0 118.2,203.6 119.1,203.6 119.1,204.3 120.0,204.3 120.0,202.7 120.9,202.7 120.9,203.3 121.8,203.3 121.8,203.9 122.7,203.9 122.7,204.2 123.6,204.2 123.6,202.8 124.6,202.8 124.6,203.1 125.5,203.1 125.5,204.3 126.4,204.3 126.4,204.4 127.3,204.4 127.3,204.0 128.2,204.0 128.2,208.3 129.1,208.3 129.1,203.7 130.0,203.7 130.0,206.9 130.9,206.9 130.9,205.9 131.8,205.9 131.8,205.4 132.7,205.4 132.7,205.2 133.6,205.2 133.6,205.8 134.5,205.8 134.5,205.3 135.4,205.3 135.4,205.6 136.3,205.6 136.3,206.3 137.2,206.3 137.2,205.4 138.1,205.4 138.1,204.7 139.0,204.7 139.0,204.5 139.9,204.5 139.9,206.0 140.8,206.0 140.8,204.5 141.7,204.5 141.7,204.0 142.7,204.0 142.7,204.2 143.6,204.2 143.6,205.5 144.5,205.5 144.5,203.8 145.4,203.8 145.4,203.9 146.3,203.9 146.3,203.8 147.2,203.8 147.2,204.5 148.1,204.5 148.1,204.0 149.0,204.0 149.0,203.8 149.9,203.8 149.9,204.8 150.8,204.8 150.8,203.1 151.7,203.1 151.7,203.2 152.6,203.2 152.6,204.6 153.5,204.6 153.5,208.3 154.4,208.3 154.4,204.2 155.3,204.2 155.3,207.4 156.2,207.4 156.2,204.3 157.1,204.3 157.1,208.3 158.0,208.3 158.0,204.9 158.9,204.9 158.9,204.8 159.8,204.8 159.8,208.9 160.8,208.9 160.8,207.9 161.7,207.9 161.7,206.2 162.6,206.2 162.6,204.1 163.5,204.1 163.5,204.0 164.4,204.0 164.4,204.1 165.3,204.1 165.3,202.0 166.2,202.0 166.2,205.5 167.1,205.5 167.1,202.9 168.0,202.9 168.0,203.2 168.9,203.2 168.9,202.5 169.8,202.5 169.8,203.5 170.7,203.5 170.7,203.1 171.6,203.1 171.6,203.0 172.5,203.0 172.5,204.8 173.4,204.8 173.4,202.8 174.3,202.8 174.3,202.1 175.2,202.1 175.2,202.3 176.1,202.3 176.1,202.8 177.0,202.8 177.0,202.8 177.9,202.8 177.9,202.2 178.9,202.2 178.9,202.8 179.8,202.8 179.8,203.6 180.7,203.6 180.7,204.0 181.6,204.0 181.6,203.8 182.5,203.8 182.5,203.6 183.4,203.6 183.4,203.2 184.3,203.2 184.3,203.7 185.2,203.7 185.2,204.9 186.1,204.9 186.1,208.0 187.0,208.0 187.0,205.1 187.9,205.1 187.9,206.4 188.8,206.4 188.8,205.3 189.7,205.3 189.7,205.4 190.6,205.4 190.6,206.9 191.5,206.9 191.5,204.8 192.4,204.8 192.4,205.4 193.3,205.4 193.3,203.5 194.2,203.5 194.2,205.7 195.1,205.7 195.1,204.4 196.1,204.4 196.1,204.9 197.0,204.9 197.0,205.1 197.9,205.1 197.9,204.8 198.8,204.8 198.8,204.4 199.7,204.4 199.7,204.8 200.6,204.8 200.6,205.2 201.5,205.2 201.5,203.8 202.4,203.8 202.4,204.7 203.3,204.7 203.3,204.7 204.2,204.7 204.2,203.5 205.1,203.5 205.1,203.3 206.0,203.3 206.0,203.7 206.9,203.7 206.9,205.0 207.8,205.0 207.8,205.4 208.7,205.4 208.7,203.9 209.6,203.9 209.6,204.8 210.5,204.8 210.5,204.9 211.4,204.9 211.4,206.4 212.3,206.4 212.3,205.0 213.2,205.0 213.2,204.4 214.2,204.4 214.2,204.7 215.1,204.7 215.1,205.1 216.0,205.1 216.0,204.9 216.9,204.9 216.9,204.5 217.8,204.5 217.8,203.7 218.7,203.7 218.7,203.3 219.6,203.3 219.6,203.5 220.5,203.5 220.5,204.1 221.4,204.1 221.4,205.9 222.3,205.9 222.3,205.1 223.2,205.1 223.2,204.7 224.1,204.7 224.1,207.3 225.0,207.3 225.0,205.1 225.9,205.1 225.9,208.6 226.8,208.6 226.8,204.2 227.7,204.2 227.7,203.8 228.6,203.8 228.6,203.0 229.5,203.0 229.5,203.7 230.4,203.7 230.4,205.8 231.3,205.8 231.3,204.8 232.3,204.8 232.3,204.7 233.2,204.7 233.2,203.5 234.1,203.5 234.1,203.6 235.0,203.6 235.0,208.2 235.9Line truncated
<circle class="nj-charts-json-dot" cx="256.7" cy="152.2" r="3.5"><title>#5328: 2.2&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="256.7" y1="54.0" x2="256.7" y2="147.2"/>
<text class="nj-charts-note" x="256.7" y="50.0" text-anchor="middle">#5328</text>
<circle class="nj-charts-json-dot" cx="295.6" cy="121.0" r="3.5"><title>#5824: 3.5&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="295.6" y1="41.0" x2="295.6" y2="116.0"/>
<text class="nj-charts-note" x="295.6" y="37.0" text-anchor="middle">#5824</text>
<circle class="nj-charts-json-dot" cx="309.2" cy="93.7" r="3.5"><title>#5885: 5.1&#215;</title></circle>
<line class="nj-charts-grid" stroke-dasharray="2 2" x1="309.2" y1="54.0" x2="309.2" y2="88.7"/>
<text class="nj-charts-note" x="309.2" y="50.0" text-anchor="middle">#5885</text>
<line class="nj-charts-axis" x1="44" y1="208" x2="330" y2="208"/>
</svg>

After

Width:  |  Height:  |  Size: 9.7 KiB

@@ -0,0 +1,80 @@
<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&#x27;s D&#8203;OM, Boost.J&#8203;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&#8203;OM 2.92 GB/s; twitter.json Boost.J&#8203;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&#8203;OM 3.52 GB/s; citm_catalog.json Boost.J&#8203;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&#8203;OM 1.07 GB/s; canada.json Boost.J&#8203;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&#8203;OM 2.07 GB/s; jeopardy.json Boost.J&#8203;SON 0.62 GB/s; jeopardy.json json::parse 0.33 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"/>
<text class="nj-charts-leg" x="156.2" y="20.5">yyjson</text>
<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&#8203;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&#8203;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&#8203;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&#8203;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&#8203;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&#8203;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&#8203;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&#8203;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&#8203;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&#8203;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"/>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

+3
View File
@@ -104,6 +104,8 @@ nav:
- 'v2.0.0': home/releases/v2.0.0.md - 'v2.0.0': home/releases/v2.0.0.md
- 'v1.1.0': home/releases/v1.1.0.md - 'v1.1.0': home/releases/v1.1.0.md
- 'v1.0.0': home/releases/v1.0.0.md - 'v1.0.0': home/releases/v1.0.0.md
- Blog:
- 'How 3.13.0 got faster': home/blog/how_3_13_0_got_faster.md
- home/design_goals.md - home/design_goals.md
- home/architecture.md - home/architecture.md
- home/customers.md - home/customers.md
@@ -609,6 +611,7 @@ plugins:
Home: Home:
- index.md - index.md
- home/*.md - home/*.md
- home/blog/*.md
Features: Features:
- features/*.md - features/*.md
- features/binary_formats/*.md - features/binary_formats/*.md
@@ -0,0 +1,318 @@
index,commit,date,pr,subject,parse_twitter,parse_citm,parse_canada,parse_citm_compact,parse_twitter_ifstream,accept_twitter,dump_twitter,dump_citm,dump_canada,dump4_citm,from_cbor_twitter,to_cbor_twitter,copy_destroy_citm,equal_citm,view_parse_twitter,view_parse_citm,view_parse_canada
0,55f93686c0,2025-04-11,,Merge branch 'release/3.12.0',3571.487,8219.609,17049.073,4366.792,3846.006,2394.213,1441.213,1375.446,7510.989,1917.809,3463.281,695.524,1643.327,1956.891,,,
1,1705bfe914,2025-04-11,4727,:bookmark: set version to 3.12.0 (#4727),3589.331,8245.422,17079.250,4422.711,3894.787,2397.597,1440.546,1377.745,7514.698,1922.371,3498.997,695.559,1655.240,1967.301,,,
2,4cca3b9cb2,2025-04-13,4738,Fix warning and add emscripten CI step (#4738),3559.657,8195.105,17066.291,4373.011,3794.269,2388.900,1419.182,1355.724,7420.703,1912.038,3468.667,664.214,1631.610,1939.475,,,
3,96c1b52f1c,2025-04-15,4742,Fix conversion to std::optional (#4742),3573.838,8157.276,16993.208,4383.656,3858.927,2395.092,1438.169,1372.208,7497.776,1925.481,3482.185,667.895,1633.619,1946.687,,,
4,88c92e605c,2025-04-16,4744,Fix compilation failure and warnings with NVHPC (#4744),3563.149,8039.911,16922.739,4381.927,3768.560,2385.086,1407.564,1345.578,7370.063,1897.474,3462.010,662.955,1623.286,1925.804,,,
5,c67d538274,2025-04-17,4749,Fix C4702 warning and extend MSVC CI job (#4749),3585.422,8251.057,17050.448,4400.542,3896.586,2390.655,1440.391,1371.722,7453.474,1921.277,3478.523,667.911,1636.206,1939.531,,,
6,756ca22ec5,2025-04-23,4736,Provide fallback for missing `char8_t` support (#4736),3559.146,8139.703,17085.114,4387.658,3856.745,2392.849,1424.997,1370.599,7477.537,1907.661,3484.427,665.541,1634.156,1957.401,,,
7,6b9199382b,2025-04-27,4763,Add missing header (#4763),3541.323,8077.761,17011.636,4359.183,3842.380,2396.686,1421.116,1363.737,7431.375,1902.909,3474.250,664.442,1625.644,1934.732,,,
8,3b02afb9d9,2025-04-28,4760,Specialize char_traits for std::byte to fix from_msgpack (fixes #4756) (#4760),3583.070,8198.146,17134.698,4381.743,3899.872,2409.185,1440.233,1380.810,7504.838,1921.781,3500.125,666.078,1657.207,1966.036,,,
9,eef76c200e,2025-04-28,4764,Make library work with C++20 modules (#4764),3528.529,8080.458,16936.656,4330.570,3764.287,2363.848,1407.851,1358.079,7356.239,1897.423,3455.287,665.194,1632.255,1937.675,,,
10,dff2b4756c,2025-04-29,4765,fix: BJData size calculation overflow (#4765),3553.706,8141.375,17047.511,4360.144,3797.070,2389.756,1417.737,1364.718,7454.313,1921.962,3479.878,666.456,1644.760,1944.696,,,
11,9110918cf8,2025-05-04,4748,Fix typos (#4748),3563.682,8176.427,17239.354,4398.055,3891.669,2399.782,1441.669,1387.133,7516.073,1925.323,3483.271,669.348,1647.760,1957.747,,,
12,46e7cd3dc2,2025-05-16,4775,Replace deprecated std::is_trivial in C++26 (#4775),3565.242,8195.396,17135.646,4373.479,3851.604,2392.258,1418.425,1370.958,7464.854,1909.844,3485.046,665.606,1643.155,1952.329,,,
13,828c891427,2025-05-16,4786,Extend type_name() to invalid type (#4786),3549.573,8103.761,17066.198,4359.911,3804.849,2389.121,1428.584,1366.405,7424.838,1914.434,3452.497,667.452,1632.750,1928.324,,,
14,4b17f90f65,2025-05-22,4609,Add `ignore_trailing_commas` option (#4609),3544.662,8132.052,16997.375,4344.592,3825.765,2382.755,1408.435,1367.468,7460.448,1924.522,3434.062,733.089,1631.356,1891.572,,,
15,b19f058465,2025-06-01,4802,Encode infinity and NaN as float for MsgPack and CBOR (#4802),3550.020,8126.438,17350.885,4327.596,3825.419,2389.356,1409.422,1376.649,7363.802,1921.226,3441.081,683.190,1624.144,1886.388,,,
16,cf16c5ab9f,2025-06-02,4805,Use binary_t::value_type (#4805),3551.735,8143.521,17153.291,4309.477,3829.229,2387.640,1428.550,1385.585,7415.271,1932.347,3425.838,657.735,1631.586,1888.954,,,
17,d70e46bc65,2025-06-25,4830,:bug: add missing header to input_adapters.hpp (#4830),3546.448,8157.469,17062.364,4335.300,3805.221,2382.796,1422.863,1382.581,7411.401,1928.676,3433.190,691.842,1632.972,1892.453,,,
18,30d27df61c,2025-07-31,4871,Fix CI (#4871),3570.015,8150.859,17070.625,4330.078,3806.505,2400.329,1434.947,1381.065,7425.718,1931.556,3429.632,656.545,1633.515,1892.916,,,
19,efcf9efb4f,2025-08-02,4873,Fixes #4854 Explicitly handle nullptr in sax_parse (#4873),3520.381,8050.719,16883.042,4331.820,3861.906,2368.069,1408.435,1375.954,7363.651,1898.466,3432.992,653.988,1634.141,1894.948,,,
20,4106af8d92,2025-08-20,4896,":rotating_light: suppress cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator (#4896)",3540.599,8175.265,17010.438,4345.182,3866.833,2393.935,1435.100,1389.496,7453.724,1945.791,3433.169,657.446,1638.434,1900.360,,,
21,a63795caf1,2025-10-22,4791,:rotating_light: avoid deprecation warning (#4791),3550.057,8174.646,16983.177,4363.521,3888.336,2393.305,1423.434,1376.334,7469.407,1936.013,3447.279,666.706,1645.354,1903.707,,,
22,1cc56b2dcd,2025-10-23,4957,Address CWG issue 2521 (#4957),3557.396,8119.651,17072.730,4351.881,3834.739,2386.097,1442.100,1393.245,7474.463,1932.315,3446.883,660.187,1638.983,1896.000,,,
23,54be9b04f0,2025-10-23,4960,:page_facing_up: update REUSE (#4960),3554.625,8098.287,17115.219,4324.578,3809.950,2390.791,1424.488,1376.715,7422.828,1913.208,3424.693,659.030,1623.405,1892.756,,,
24,29913ca760,2025-10-25,4963,Add char8_t* overload for _json and _json_pointer (#4963),3544.899,8169.203,17007.844,4353.594,3797.630,2392.108,1423.032,1375.216,7349.787,1909.897,3428.771,655.625,1635.273,1891.018,,,
25,515d994acb,2026-01-01,5044,:page_facing_up: adjust year (#5044),3524.610,8059.521,16949.416,4313.508,3773.750,2364.742,1410.427,1372.988,7382.438,1915.502,3403.159,643.968,1618.972,1884.213,,,
26,8f75700141,2026-01-11,4958,support types convertible to string_view as JSON keys (#4958),3546.757,8142.599,17103.386,4327.739,3825.990,2388.540,1420.515,1379.309,7413.062,1924.540,3433.677,658.266,1628.079,1890.759,,,
27,457bc283ff,2026-01-12,5039,fix(cbor): reject overflowing negative integers (#5039),3508.883,8077.291,16930.011,4305.982,3785.698,2378.693,1425.526,1366.111,7407.042,1929.142,3478.909,657.722,1636.304,1944.681,,,
28,e3014f162a,2026-01-13,5052,Fix conversion to std::optional (#5052),3547.995,8140.052,17010.031,4321.914,3797.807,2385.856,1430.414,1386.202,7407.260,1930.403,3462.213,657.829,1629.579,1932.066,,,
29,5ed07097fa,2026-01-13,5050,Fix -Wtautological-constant-out-of-range-compare in serializer (#5050),3544.136,8180.208,17033.209,4339.591,3799.779,2391.940,1427.870,1387.871,7368.765,1922.321,3454.938,659.367,1630.707,1959.722,,,
30,25f48639c7,2026-01-23,5016,Reference tuple from json (#5016),3563.180,8209.037,17030.969,4388.675,3895.086,2392.088,1430.666,1393.853,7528.567,1934.347,3481.351,677.234,1645.418,1957.591,,,
31,f8eee1bb79,2026-02-07,5071,Annotate unreachable comment-scanner switch paths to satisfy C26819 (#5071),3508.000,8128.750,16958.959,4315.235,3797.237,2371.963,1425.146,1374.867,7453.381,1930.211,3456.508,658.568,1629.188,1909.736,,,
32,fd17b0889e,2026-05-08,5139,Remove nullptr safety check from sax_parse functions (#5139),3544.101,8033.021,16963.292,4334.102,3800.736,2382.583,1419.050,1361.745,7357.073,1907.153,3429.315,657.041,1618.815,1937.829,,,
33,62f3b41b30,2026-05-08,5090,fix: treat single-element brace-init as copy/move instead of wrapping in array (#5074) (#5090),3550.323,8168.713,17060.031,4349.417,3794.110,2380.583,1416.822,1361.182,7369.651,1897.717,3466.731,659.297,1631.463,1941.905,,,
34,4fad446897,2026-05-10,5162,docs: add IDs to @requirement tags to fix Doxygen autolinking (#5162),3545.440,8031.891,17069.448,4324.698,3802.862,2383.513,1422.768,1384.602,7325.776,1917.606,3469.787,659.011,1631.296,1940.370,,,
35,a0a4e7cc0b,2026-05-13,5152,Add front methods to json_pointers (implements #4889) (#5152),3582.898,8215.010,17034.448,4345.515,3891.513,2396.572,1432.733,1395.714,7554.119,1934.008,3484.859,659.298,1642.314,1957.356,,,
36,93e49decbd,2026-05-14,5167,Fix incomplete-type error in set_parents with ordered_json (#5167),3555.224,8147.771,17017.073,4320.846,3831.318,2386.750,1435.840,1385.578,7436.864,1927.483,3466.508,658.409,1632.724,1939.528,,,
37,7192763f15,2026-05-14,5163,Fix compile error when using nlohmann ordered_map with WITH_DEFAULT macros (#5163),3520.675,8039.145,16892.291,4303.448,3769.198,2363.337,1410.030,1364.679,7380.797,1913.285,3437.278,660.130,1630.738,1943.235,,,
38,5a05627b1f,2026-05-14,5169,:rotating_light: fix warning (#5169),3600.555,8160.854,16979.031,4324.070,3887.823,2389.157,1430.983,1387.106,7509.984,1912.601,3473.713,663.279,1652.982,1958.774,,,
39,bb5404bb86,2026-05-15,5164,Fix GCC C++20 modules compilation #5103 (#5164),3543.823,8120.266,17015.395,4349.300,3794.880,2364.178,1414.408,1374.548,7484.218,1920.495,3444.266,699.326,1626.241,1954.688,,,
40,b1bb9fce0c,2026-05-15,3929,Fix for printing long doubles bug in dump_float (#3929),3549.378,8089.891,16934.927,4313.310,3824.802,2386.958,1412.164,1385.425,7417.869,1930.513,3461.151,651.557,1618.735,1944.450,,,
41,cba5dc0ed8,2026-05-16,4563,New macros for the named JSON convertor generation (#4563),3544.657,8168.182,16990.886,4327.688,3806.963,2370.975,1421.629,1390.206,7454.151,1919.284,3452.456,677.413,1623.622,1941.921,,,
42,47202c804a,2026-05-18,5171,Add missing overload to ordered_map::find (#5171),3527.542,8168.312,17141.989,4409.456,3887.378,2397.007,1428.765,1387.033,7495.604,1935.710,3485.088,660.155,1648.977,1951.430,,,
43,58cfecf7f7,2026-05-18,5151,Serialize enum (#5151),3521.302,8100.104,16805.489,4288.463,3763.971,2381.494,1408.713,1383.059,7328.261,1915.202,3440.372,648.726,1617.661,1922.608,,,
44,584e6b1cfb,2026-05-22,5187,Fix: update() parent pointers not updated after recursive merge with JSON_DIAGNOSTICS (#5187),3550.639,8083.463,17055.198,4326.833,3804.257,2381.519,1432.039,1381.986,7377.844,1915.159,3460.750,656.873,1631.527,1940.953,,,
45,02dfbea39d,2026-06-17,5209,added explicit instantiations of 'has_from_json' and 'has_to_json' for std_fs::path (#5209),3552.209,8215.474,17167.760,4338.404,3845.144,2398.026,1425.012,1387.629,7458.614,1931.388,3475.343,658.183,1644.329,1958.324,,,
46,fc1df0b7db,2026-06-23,5172,:recycle: remove unnecessary if (#5172),3562.088,8175.531,17044.042,4336.583,3863.651,2404.695,1425.872,1389.434,7523.855,1914.128,3481.000,653.259,1639.515,1957.649,,,
47,c5b2b26fdc,2026-06-29,5217,:memo: fix docs (#5217),3526.825,8052.307,17000.011,4343.963,3793.412,2388.194,1416.706,1374.177,7361.646,1904.008,3463.919,658.322,1627.765,1921.887,,,
48,b7566c6293,2026-06-30,5161,Harden JSON_HAS_RANGES detection for incomplete C++20 ranges implementations (#5161),3538.995,8071.787,17120.751,4318.797,3772.445,2384.008,1421.440,1385.239,7419.292,1898.929,3431.466,647.948,1602.258,1928.644,,,
49,adf78d3a76,2026-06-30,5215,Minor: unique_ptr template resolution workaround for MSVC (#5215),3550.380,8138.026,17036.802,4366.062,3842.430,2389.536,1426.658,1385.609,7428.787,1915.233,3467.188,658.332,1636.158,1942.556,,,
50,272411c5e6,2026-06-30,5218,Overwork project infrastructure (#5218),3547.487,8087.250,16962.198,4341.969,3793.831,2387.509,1420.888,1381.072,7450.078,1930.003,3466.193,659.676,1631.329,1943.043,,,
51,730b57775d,2026-07-01,5222,:bug: avoid assertion in patch (#5222),3539.912,8169.771,17027.229,4345.151,3790.753,2376.552,1421.263,1386.717,7399.985,1923.237,3455.722,653.609,1630.914,1934.028,,,
52,ca49ab6123,2026-07-02,5223,Extend value to arrays when using JSON pointers (#5223),3550.341,8113.787,16951.313,4346.805,3793.097,2391.224,1409.695,1380.075,7374.073,1926.401,3458.438,659.382,1629.387,1941.306,,,
53,8d7e0046f4,2026-07-02,5224,Add std::format and fmt support (#5224),3546.935,8170.406,16968.927,4346.906,3814.956,2387.612,1424.861,1386.542,7350.765,1900.376,3461.177,662.476,1633.858,1930.434,,,
54,31dd15b258,2026-07-02,5221,Fix ambiguous static_cast (#5221),3551.945,8213.000,17131.271,4373.620,3845.763,2393.074,1438.633,1385.769,7471.146,1927.804,3486.568,662.015,1631.810,1958.901,,,
55,eed1587000,2026-07-05,5234,Reconstruct lexer diagnostics lazily for seekable input (#120) (#5234),3145.909,5311.094,15381.843,4292.961,3851.260,1966.833,1422.598,1365.461,7443.276,1920.467,3467.060,702.832,1637.587,1905.758,,,
56,83c87cb9e0,2026-07-05,5233,Read binary strings/blobs in bulk chunks with a memcpy fast path (#5233),3141.867,5259.485,15454.959,4326.664,3797.198,1987.623,1406.492,1372.765,7424.729,1899.726,2363.895,667.502,1630.097,1888.392,,,
57,acf076a677,2026-07-06,5238,Fix ADL leak of nlohmann::detail through basic_json's default base class (#5238),3152.153,5277.073,15291.407,4338.828,3839.331,1995.524,1429.960,1365.917,7456.776,1907.928,2398.016,670.257,1627.590,1897.997,,,
58,c05c5e229b,2026-07-07,5241,Add missing copyright notices to SBOM (#5241),3147.485,5268.865,15319.584,4321.823,3796.972,1981.167,1432.689,1371.264,7465.416,1918.083,2388.154,667.119,1630.745,1891.583,,,
59,366f3d26e5,2026-07-08,5235,Replace snprintf with a branch-free writer for \uXXXX escapes (#5235),3127.641,5272.302,15425.239,4340.459,3850.357,1997.957,1459.603,1356.461,7509.703,1899.916,2366.966,668.383,1624.981,1889.145,,,
60,f8e99e856c,2026-07-09,5248,Fix nvcc CUDA 12.0/12.1 C++20 ranges parse error (#3907) (#5248),3132.099,5226.375,15164.510,4301.901,3769.651,1967.647,1456.759,1365.810,7530.724,1908.635,2381.610,683.815,1616.699,1879.795,,,
61,855f511db4,2026-07-09,5250,Fix stale Clang -Weverything suppression comments; drop -Wno-missing-noreturn (#5250),3126.792,5208.338,15352.520,4293.596,3800.544,1969.497,1458.601,1329.851,7372.849,1876.404,2368.894,662.173,1603.881,1874.673,,,
62,d0a43141ea,2026-07-09,5253,Fix #3868: Remove operator!= to enable P2468R2 rewritten candidate synthesis (#5253),3165.182,5270.458,15479.031,4302.729,3845.646,1989.231,1474.135,1343.312,7443.282,1887.909,2392.523,670.395,1634.871,1894.474,,,
63,b630f5e9c7,2026-07-10,5260,Fix container input_adapter SFINAE for lvalue-only ADL begin/end (#5260),3128.117,5263.807,15375.677,4330.544,3819.953,1982.196,1454.088,1339.062,7364.683,1877.699,2361.482,666.486,1616.514,1920.626,,,
64,c60217e801,2026-07-11,5205,fix: support constructing json from C++20 range views (#4916) (#5205),3117.539,5206.552,15308.166,4320.513,3798.713,1983.458,1447.072,1350.950,7357.213,1875.632,2340.731,662.905,1633.357,1934.261,,,
65,fe2bcc080f,2026-07-11,5266,Custom BinaryType direct assignment (#5266),3174.528,5284.562,15383.645,4328.120,3895.086,1996.913,1478.427,1355.569,7512.115,1899.236,2398.490,672.118,1642.910,1967.660,,,
66,ca76c37650,2026-07-11,5265,Add iterator+sentinel tests and docs for binary deserializers (#5265),3134.265,5218.021,15352.521,4306.284,3791.612,1967.824,1451.953,1358.685,7508.828,1891.697,2377.848,665.474,1631.495,1934.907,,,
67,c197feff81,2026-07-12,5268,Extend memcpy fast path to sized sentinels (e.g. std::counted_iterator) (#5268),3116.271,5207.146,15415.771,4272.443,3815.851,1984.966,1451.103,1341.093,7328.037,1865.385,2383.169,664.494,1617.967,1915.428,,,
68,1c5a953de5,2026-07-19,5276,reject unpaired UTF-16 surrogates in wide-string input (#5276),3155.360,5299.631,15419.812,4302.089,3853.104,1987.259,1468.653,1349.665,7549.432,1911.365,2457.555,680.311,1653.282,1955.673,,,
69,3565f40229,2026-07-20,5284,reject negative UBJSON/BJData string length (#5284),3170.456,5301.698,15404.416,4351.226,3893.594,1997.034,1470.907,1358.245,7491.480,1909.601,2401.384,671.260,1639.865,1963.899,,,
70,9a3ebb9456,2026-07-23,5287,validate BSON document size against the bytes read (#5287),3157.646,5264.062,15305.271,4338.672,3839.643,1987.196,1461.356,1351.630,7444.791,1890.626,2398.503,665.262,1655.798,1930.268,,,
71,8ec98e2c9e,2026-07-27,5313,adding cleanups to bson writer (#5313),3150.448,5268.948,15445.927,4308.612,3805.005,1989.643,1466.348,1349.591,7326.453,1895.842,2393.278,708.164,1644.025,1946.652,,,
72,2e23687092,2026-07-28,5314,to_bson() silently emits corrupt documents when a length exceeds INT32_MAX (#5314),3146.534,5254.547,15445.250,4304.008,3798.620,1986.260,1459.735,1345.534,7517.651,1903.996,2395.155,674.344,1644.565,1952.682,,,
73,868506dcc0,2026-07-30,5335,Fix CBOR half-float assertion bounds (#5335),3167.086,5267.068,15397.979,4351.011,3883.135,2003.345,1468.939,1360.483,7455.230,1909.055,2406.305,679.942,1643.646,1945.639,,,
74,dd24e2dffd,2026-07-30,5332,check all BSON reads and add an EOF check for booleans (#5332),3138.315,5284.833,15399.166,4310.513,3847.630,1980.682,1464.104,1344.108,7445.146,1901.512,2400.532,670.850,1635.196,1900.946,,,
75,fd72ecfc8c,2026-07-31,5301,validate ndarray element types in write_bjdata_ndarray (#5301),3164.662,5262.141,15399.010,4287.271,3849.318,1988.186,1460.688,1353.767,7458.380,1893.669,2398.485,668.466,1644.018,1921.615,,,
76,bc48951128,2026-07-31,5323,Fix UBJSON high-precision floating-point overflow handling (#5323),3155.628,5289.864,15474.375,4324.253,3888.966,2015.068,1477.846,1354.622,7480.730,1905.566,2415.428,668.997,1641.776,1911.819,,,
77,d94cbd99dc,2026-07-31,5274,reject CBOR array/map length equal to the indefinite-length marker (#5274),3144.041,5272.193,15466.980,4338.735,3848.849,1999.231,1459.129,1358.119,7507.307,1901.807,2394.972,667.016,1635.960,1899.878,,,
78,2222d386c9,2026-07-31,5339,fix: check CBOR tagged subtype reads (#5339),3095.768,5137.792,15064.146,4258.977,3755.229,1965.900,1454.890,1338.066,7399.068,1883.624,2358.193,660.190,1618.172,1939.713,,,
79,585929bff9,2026-08-03,5289,Fix Clang deprecation warning for json_pointer operator== with ordered_json (#5289),3142.341,5259.360,15258.271,4275.479,3807.672,1969.704,1453.688,1337.633,7451.037,1879.447,2364.966,661.560,1635.617,1945.709,,,
80,5f121d8c50,2026-08-03,5336,avoid sign extension in char_traits<signed char>::to_int_type (#5336),3145.000,5264.880,15441.521,4269.632,3796.781,1983.497,1440.810,1325.232,7427.750,1880.047,2361.899,663.772,1621.595,1912.378,,,
81,68f0722a19,2026-08-03,5342,remove discarded array from parent object in end_array (#5342),3161.273,5269.907,15312.469,4335.433,3840.510,1995.965,1465.745,1355.934,7474.901,1895.483,2401.197,657.397,1634.791,1901.902,,,
82,dca9d49a33,2026-08-05,5348,reject out-of-range code points in UTF-32 wide-string input (#5348),3119.753,5210.979,15209.260,4273.984,3799.034,1995.297,1459.456,1342.982,7431.646,1891.478,2370.364,653.618,1633.585,1882.753,,,
83,9a091d2b82,2026-08-05,5362,Do not write BJData ndarrays whose size overflows std::size_t (#5362),3137.381,5257.312,15286.084,4308.500,3805.325,1995.140,1468.138,1354.729,7510.088,1893.036,2384.577,659.394,1628.260,1890.245,,,
84,d5647e6a3b,2026-08-05,5355,Resolve the TODO(niels) in get_ubjson_string (#5355),3121.278,5249.927,15246.011,4292.737,3800.490,1967.087,1443.762,1333.226,7368.953,1862.131,2347.852,644.647,1623.909,1889.958,,,
85,bacdabd176,2026-08-05,5361,Fix start_pos() for strings containing escape sequences (#5361),3114.653,5251.619,15253.907,4331.818,3786.156,1960.676,1442.388,1330.247,7354.724,1863.306,2351.588,650.781,1623.543,1886.671,,,
86,1c136a66c4,2026-08-06,5363,Move the CBOR doc block to the function it describes (#5363),3124.274,5209.615,15411.897,4293.320,3812.156,1982.854,1457.653,1345.680,7422.343,1884.848,2387.050,656.076,1627.620,1878.737,,,
87,6285225fd0,2026-08-12,5211,Fix integer comparison bug (#5211),3159.557,5291.323,15395.395,4329.836,3867.200,1989.476,1456.052,1359.795,7526.860,1879.642,2396.137,659.077,1638.176,1900.416,,,
88,b5378e8deb,2026-08-19,5331,Fix CBOR tag handlers not recognizing tags 0-5 and 21-23 (#5331),3172.476,5239.812,15479.917,4295.539,3871.289,2003.439,1473.447,1343.742,7516.875,1888.412,2400.572,645.588,1641.621,1886.531,,,
89,2f025f401e,2026-08-25,5380,Throw other_error.502 when UBJSON use_type is set without use_size (#5380),3155.873,5190.312,15144.406,4286.388,3793.805,1968.199,1442.240,1340.929,7373.610,1860.543,2370.570,648.906,1631.207,1893.750,,,
90,35705d79d8,2026-08-28,5414,Fix update(merge_objects=true) throwing on primitive-to-object merge (#5414),3169.029,5252.578,15387.292,4340.690,3893.646,1979.616,1472.286,1361.543,7491.302,1903.909,2401.404,659.396,1641.697,1912.409,,,
91,137a40b9aa,2026-09-05,5459,Compare integers with floats exactly instead of widening the integer (#5459),3134.229,5259.349,15404.541,4300.146,3846.646,1992.155,1467.919,1351.774,7467.146,1887.255,2391.467,660.347,1631.735,1891.751,,,
92,3c875683a5,2026-09-05,5461,Make diff() linear when an array shrinks (#5461),3141.068,5259.000,15271.166,4319.659,3797.088,1983.450,1455.354,1354.676,7444.860,1891.687,2389.333,657.163,1632.998,1887.016,,,
93,09b6b6b5ba,2026-09-05,5455,Fix to_bjdata() emitting unparsable output when _ArraySize_ is not an array (#5455),3161.542,5253.047,15311.718,4291.388,3834.264,1992.744,1472.685,1357.680,7409.479,1889.287,2389.501,698.680,1628.237,1888.705,,,
94,faa35cc647,2026-09-09,5484,Skip integer conversion in accept()/SAX validation when the value is unused (#5484),3103.654,5222.453,15458.573,4215.765,3804.320,1935.161,1468.660,1353.499,7452.052,1883.191,2383.524,654.441,1631.700,1885.664,,,
95,6d86cc0f6b,2026-09-09,5490,Speed up whitespace skipping in the lexer (#5490),3181.328,5276.318,15307.312,4262.771,3877.401,1977.062,1465.196,1356.119,7594.177,1906.814,2388.615,684.926,1636.950,1893.526,,,
96,c05347dd54,2026-09-09,5475,Undefine the four JSON_HEDLEY_* macros that leak after including json.hpp (#5475),3147.932,5156.625,15347.990,4217.505,3871.812,1982.807,1458.787,1354.934,7639.328,1879.823,2370.342,674.625,1637.257,1903.903,,,
97,d6660cf718,2026-09-09,5485,Route hand-rolled diagnostic pragmas through Hedley (#5485),3116.151,5215.531,15257.499,4189.979,3835.023,1974.111,1459.363,1342.996,7553.802,1887.698,2379.999,669.934,1635.350,1877.492,,,
98,c9477ccf91,2026-09-09,5496,Throw when JSON Patch remove's target path resolves through a primitive or null parent (#5496),3138.841,5258.401,15315.417,4201.008,3874.682,1967.630,1446.393,1335.060,7542.708,1870.111,2390.141,668.484,1634.138,1886.981,,,
99,8c38e270b5,2026-09-09,5497,Reject JSON Patch move when from is a proper prefix of path (#5497),3183.820,5280.000,15346.969,4222.164,3839.596,1970.753,1470.428,1351.838,7515.344,1895.809,2389.731,673.696,1633.247,1889.546,,,
100,a316738cfa,2026-09-09,5471,Add JSON_HEDLEY_WARN_UNUSED_RESULT to the current accept() overloads (#5471),3175.891,5281.302,15397.062,4240.576,3934.333,1981.765,1475.890,1353.387,7625.104,1896.181,2401.097,669.729,1646.133,1895.638,,,
101,c9f1d2d646,2026-09-09,5477,Broaden JSON_HEDLEY_WARN_UNUSED_RESULT coverage to pure query functions (#5477),3171.706,5286.880,15430.844,4264.242,3880.943,1979.990,1472.289,1357.283,7569.854,1904.026,2407.487,671.673,1641.521,1889.053,,,
102,8e26b9d4b3,2026-09-09,5495,Make contains(json_pointer) return false instead of throwing on unrepresentable array-index tokens (#5495),3163.789,5240.755,15337.698,4226.154,3880.956,1971.912,1475.322,1357.125,7632.281,1904.060,2401.190,678.863,1638.371,1903.385,,,
103,b17c272f46,2026-09-09,5472,Reserve capacity in from_json() object conversion when the target container supports it (#5472),3152.899,5257.645,15401.000,4210.846,3885.123,1989.159,1476.637,1359.851,7639.396,1898.981,2408.243,670.075,1633.528,1894.086,,,
104,3e2de32226,2026-09-10,5516,Remove unused iomanip include (#5516),3141.349,5253.657,15364.074,4203.969,3847.620,1968.422,1455.035,1352.754,7582.494,1882.051,2371.814,663.504,1630.172,1870.223,,,
105,d69fb8654d,2026-09-10,5501,Return the parsed value by move from from_cbor() and friends (#5501),3133.485,5231.662,15309.926,4183.200,3835.662,1971.125,1462.447,1349.563,7479.136,1904.202,1595.991,661.519,1630.278,1883.994,,,
106,4a93aa4e2f,2026-09-10,5283,"Speed up parsing of contiguous input (numbers, strings, UTF-8) (#5283)",1963.879,4221.308,11609.531,3278.497,3857.880,927.779,1483.726,1357.793,7483.343,1906.916,1481.419,676.438,1643.746,1895.551,,,
107,bfb07786cd,2026-09-10,5473,Fix to_bjdata() silently truncating out-of-range _ArrayData_ elements (#5473),1941.894,4204.971,11726.688,3264.055,3808.784,923.797,1453.071,1351.760,7458.125,1891.470,1473.508,662.164,1633.043,1888.548,,,
108,ff80ed3295,2026-09-11,5285,"Speed up dump(), and keep it from overflowing the stack (#5285)",1939.289,4175.541,11781.291,3233.302,3816.101,914.071,441.200,540.473,6895.041,852.214,1478.197,656.635,1632.675,1885.303,,,
109,da42a627dc,2026-09-11,5449,Stop dump() from heap-allocating its output adapter per call (#5449),1937.658,4200.966,11639.198,3235.493,3827.695,909.901,448.948,537.008,6909.036,839.027,1479.968,659.210,1643.621,1878.065,,,
110,1dc1d09fc6,2026-09-11,5457,Do not search a container for the value the callback rejected (#5457),1937.459,4140.078,11576.803,3271.838,3845.193,924.316,450.148,539.031,6848.776,844.624,1470.333,671.563,1645.624,1900.347,,,
111,fae364db24,2026-09-11,5458,Move the scanned string into the value instead of copying it (#5458),1986.146,4110.787,11757.157,3150.932,3830.550,918.517,442.629,539.606,6913.104,843.920,1417.037,655.259,1628.224,1892.991,,,
112,dd50f0eb16,2026-09-11,5502,Stop CBOR indefinite-length strings from recursing per chunk (#5502),1987.853,4033.182,11613.834,3116.378,3841.164,915.943,442.366,539.480,6864.130,836.458,1431.035,656.146,1599.574,1885.858,,,
113,4bb2de8cc5,2026-09-11,5503,Reject a nested BJData ndarray dimension vector where it is read (#5503),1981.298,4086.276,11569.240,3141.539,3829.870,923.087,444.038,539.863,6800.724,835.434,1429.637,655.448,1628.999,1879.300,,,
114,44f8ec30e9,2026-09-11,5504,Bound UBJSON optimized arrays of a valueless type (#5504),2005.265,4092.265,11730.198,3130.635,3863.992,925.033,448.222,542.323,6893.078,849.901,1437.855,662.171,1638.306,1896.324,,,
115,0dd8ca9023,2026-09-11,5505,Read MessagePack containers without recursing per nesting level (#5505),2019.983,4105.305,11862.979,3142.581,3891.601,927.092,447.942,543.936,6939.963,845.634,1442.889,656.578,1637.512,1897.815,,,
116,91ab3e81f5,2026-09-11,5506,Read CBOR containers and tags without recursing per nesting level (#5506),1986.334,4039.961,11554.094,3118.761,3783.101,912.504,440.410,534.894,6831.943,834.661,1439.061,655.287,1615.619,1869.912,,,
117,a14619b354,2026-09-11,5507,Read UBJSON and BJData containers without recursing per nesting level (#5507),2011.959,4095.868,11782.688,3135.264,3873.604,926.014,447.638,541.304,6905.838,846.051,1468.512,664.161,1629.083,1898.772,,,
118,0452641c18,2026-09-11,5508,Read BSON documents without recursing per nesting level (#5508),1974.160,4043.887,11662.938,3095.011,3832.744,916.007,439.914,534.149,6904.453,835.615,1450.792,648.298,1616.917,1874.133,,,
119,aa391dc0a5,2026-09-11,5520,Fix two develop CI regressions: dump() nodiscard warning and binary-reader const-correctness (#5520),2003.010,4068.010,11771.364,3137.266,3825.247,924.668,442.416,539.478,6847.083,841.996,1460.659,649.378,1633.738,1885.897,,,
120,a50c2537eb,2026-09-12,5476,Reserve capped array capacity in json_sax_dom_parser::start_array() for definite-length binary arrays (#5476),1986.488,4063.883,11588.333,3077.995,3827.479,908.419,440.959,539.114,6806.177,833.555,1452.851,662.422,1627.995,1915.388,,,
121,c0b2878a44,2026-09-13,5493,Swap diagnostic positions in basic_json::swap() (#5493),2010.881,4081.057,11734.730,3130.919,3882.258,925.490,450.092,542.953,6925.188,848.486,1480.051,698.636,1643.508,1933.941,,,
122,1da2f68992,2026-09-14,5522,Only reserve array capacity if the array type supports it (#5522),1972.122,4048.622,11775.062,3107.938,3803.528,909.385,441.204,535.885,6793.927,842.843,1446.330,658.787,1619.239,1899.164,,,
123,6487678bc5,2026-09-15,5464,Fix swap(array_t&)/swap(object_t&) to update parent pointers under JSON_DIAGNOSTICS (#5464),2023.028,4116.169,11737.438,3165.172,3893.266,924.912,448.959,541.529,6970.438,852.039,1483.231,689.631,1635.240,1937.356,,,
124,c72f37a40d,2026-09-15,5443,Support custom object/array types and improve template parameter handling (#5443),2001.617,4076.547,11666.583,3109.756,3918.206,923.197,450.592,542.266,6901.703,846.558,1468.284,660.116,1641.586,1905.840,,,
125,502e9d66f6,2026-09-16,5479,Fix to_bjdata() emitting the Draft-3-only 'B' marker in default Draft-2 mode (#5479),1970.935,4018.060,11445.500,3079.409,3809.050,910.459,444.217,539.291,6851.407,833.755,1444.697,698.040,1626.601,1889.024,,,
126,c41152e620,2026-09-16,5494,Fall back to plain-object encoding when to_bjdata()'s _ArrayType_ annotation is not a string (#5494),1979.481,4054.688,11734.292,3085.542,3819.351,916.992,445.126,539.870,6853.005,833.190,1457.166,665.391,1629.586,1888.734,,,
127,e564136c22,2026-09-22,5465,Make diff() account for member order in ordered_json objects (#5465),1970.519,4063.744,11605.198,3087.497,3848.867,915.695,447.051,539.711,6835.172,841.402,1452.004,664.560,1640.751,1890.473,,,
128,e485441123,2026-09-22,5466,Restore a duplicate key's prior value when the callback rejects its new value (#5466),2012.920,4099.265,11796.895,3156.818,3913.812,931.464,451.403,541.419,6981.041,846.536,1469.521,704.138,1633.327,1905.709,,,
129,a2b19d6158,2026-09-22,5467,Honor allow_exceptions=false for excessive array/object size (out_of_range.408) (#5467),1996.478,4084.422,11734.208,3129.099,3850.854,923.499,446.555,539.379,6949.427,842.029,1453.166,694.200,1631.133,1888.865,,,
130,d2c1a6a272,2026-09-22,5468,"Reject array insert(pos, first, last) iterators not pointing into an array (#5468)",1983.767,4066.651,11618.667,3128.505,3848.427,914.900,447.603,541.973,6915.265,844.307,1458.762,677.699,1638.789,1892.443,,,
131,0b20b7e622,2026-09-22,5469,Reject MessagePack/BSON binary subtypes that don't fit their wire format (#5469),2010.548,4097.476,11681.218,3121.010,3866.146,925.619,448.533,540.786,6957.000,843.349,1463.518,658.302,1630.857,1902.522,,,
132,1054b2097e,2026-09-23,5286,Speed up binary writing: value-type output sink + byte-swap number encoding (#5286),1989.739,4101.393,12034.438,3157.240,3853.987,910.115,449.084,555.970,6884.386,864.526,1471.905,656.635,1661.806,1926.233,,,
133,ed513715a8,2026-09-24,5534,Document that a NUL byte in the input is treated as end of input (#5534),2016.236,4104.763,11906.323,3141.138,3936.240,916.611,455.397,562.053,6987.917,871.110,1475.622,657.877,1676.934,1936.557,,,
134,56b3ee566c,2026-09-24,5389,Fix stack overflow when copying a deeply nested value (#5387) (#5389),1998.356,4051.206,11660.865,3101.107,3834.672,910.072,452.943,544.464,6908.974,849.212,1460.691,638.644,1650.749,1914.423,,,
135,918da64657,2026-09-24,5542,Keep BJData ndarray annotations that would not survive a round trip as objects (#5542),2003.009,4042.969,11517.375,3095.122,3815.360,908.444,448.415,539.423,6911.041,840.044,1449.543,671.530,1651.709,1908.408,,,
136,8699de3064,2026-09-24,5555,Stop allocating the BJData excluded-marker list per container (#5555),2001.718,4071.333,11686.427,3122.065,3796.757,900.895,447.123,539.918,6860.765,844.752,1444.435,646.608,1644.943,1879.295,,,
137,2e91641de2,2026-09-24,5544,"Test JSON_BRACE_INIT_COPY_SEMANTICS for real, and fix one-element tuples under it (#5544)",2004.785,4083.914,11662.270,3119.602,3917.914,922.465,454.869,547.631,6987.234,853.010,1469.612,649.946,1672.246,1913.098,,,
138,7c90ec2323,2026-09-24,5546,Hash deeply nested values without recursing per nesting level (#5546),1952.912,4071.159,11594.927,3117.497,3793.052,900.729,444.245,539.787,6854.406,841.264,1457.530,643.139,1638.578,1890.482,,,
139,4daca40d7b,2026-09-24,5547,Merge deeply nested objects without recursing per nesting level (#5547),2008.226,4104.399,11619.542,3148.604,3918.175,921.207,457.191,547.553,6942.265,855.352,1464.974,651.924,1665.232,1915.869,,,
140,01b53c8c15,2026-09-25,5552,Keep JSON_DIAGNOSTICS parent pointers of ordered_json members after erase() and update() (#5552),1979.354,4061.378,11603.480,3098.586,3875.258,919.125,455.911,546.269,6940.026,849.511,1461.751,648.841,1660.978,1917.254,,,
141,abbe52d6de,2026-09-25,5344,Add JSON_PRECISE_STREAM_POSITION to leave the character that terminates a number in the stream (#5344),2001.170,4081.617,11653.531,3131.331,3876.208,915.153,453.436,546.720,6971.864,848.900,1463.182,647.946,1662.943,1906.246,,,
142,02dd3e67f2,2026-09-25,5390,Fix stack overflow and exponential runtime when comparing nested values (#5390),1987.861,4074.039,11596.000,3161.284,3901.497,919.541,447.553,543.948,6910.162,845.668,1455.759,664.224,1652.074,1930.575,,,
143,465407f3ce,2026-09-25,2818,Improve error message for const fields (#2818),1975.274,4118.565,11863.448,3130.541,3880.764,910.767,452.904,545.363,6906.890,843.118,1459.728,645.770,1654.265,1934.900,,,
144,632a5812a8,2026-09-25,5272,Support zero-member types in NLOHMANN_DEFINE_TYPE_* macros (#4041) (#5272),1963.323,4021.526,11747.959,3102.006,3784.896,904.545,444.355,543.748,6840.604,841.416,1438.306,639.223,1649.816,1930.274,,,
145,d19f7f5dce,2026-09-25,5185,Fix BSON conformance issue (#5185),1958.606,4048.536,11541.011,3086.805,3817.875,900.452,446.001,544.071,6824.323,837.078,1971.245,641.271,1651.209,1934.647,,,
146,c60a0bc336,2026-09-25,5573,Allocate the deep copy's key scratch space with the provided allocator (#5573),1965.216,4021.459,11630.855,3074.078,3807.258,902.782,444.394,542.562,6919.969,840.942,1975.668,645.827,1637.429,1918.607,,,
147,1e44262091,2026-09-25,5560,Make JSON_STRICT_NUL_HANDLING part of the ABI tag (#5560),1961.862,4069.617,11594.083,3117.500,3817.758,909.186,448.820,544.420,6845.802,844.016,1977.909,645.864,1651.269,1937.217,,,
148,95e9a5931c,2026-09-25,5553,"Write BSON in linear time, without recursing per nesting level (#5553)",1965.832,4033.394,11589.364,3120.422,3792.091,905.110,446.984,543.328,6794.244,844.943,1991.659,640.188,1647.675,1928.562,,,
149,fe4a544c7e,2026-09-27,5515,handled when size exceed uint32 (#5515),1998.244,4047.208,11755.209,3091.776,3815.000,908.733,447.990,546.295,6903.084,850.946,1993.351,645.487,1654.343,1933.385,,,
150,4fa95d9810,2026-09-27,5583,Remove unreachable branches from the binary writer (#5583),1983.323,4038.331,11666.480,3092.841,3844.935,910.149,449.697,541.110,6840.583,830.604,1979.750,653.542,1650.670,1928.883,,,
151,6178982b8d,2026-09-27,5582,Compare unordered objects by key below the nesting bound (#5582),1971.706,4073.498,11600.646,3132.700,3830.323,910.231,448.982,538.812,6836.770,846.149,2007.607,657.180,1653.089,1934.675,,,
152,f7972970a4,2026-09-27,5584,Throw instead of writing MessagePack lengths beyond UINT32_MAX (#5584),1969.417,4013.021,11602.447,3083.552,3842.495,904.223,447.444,542.170,6862.735,839.628,2000.766,655.034,1653.006,1939.922,,,
153,6bd106893a,2026-09-27,5559,Fix CBOR tag handling in cbor_tag_handler_t::store for non-binary items (#5559),1969.250,4034.693,11691.500,3119.171,3827.860,916.053,455.026,542.577,6886.360,839.718,2012.919,653.031,1651.090,1931.698,,,
154,1e101ecac1,2026-09-27,2998,Add BON8 support (#2998),1975.804,4082.375,11658.542,3192.828,3758.141,907.029,444.920,556.470,6844.698,849.276,1977.153,649.181,1645.306,1920.836,,,
155,9e1a09eec0,2026-09-28,5594,Name the key type when rejecting non-string CBOR/MessagePack map keys (#5594),2006.582,4151.784,11788.532,3156.156,3845.052,915.647,454.027,557.846,6814.282,864.094,2021.072,654.095,1663.051,1947.078,,,
156,fc03b9912e,2026-09-28,5597,"Look up the locale decimal point at conversion time, not lexer construction (#5597)",2020.431,4172.916,12716.958,3196.958,3909.774,910.001,449.314,547.334,6900.968,852.306,2048.019,665.843,1696.937,1982.586,,,
157,5b9ffae8bb,2026-09-30,5616,Move the float conversion chain out of the lexer (#5616),1992.332,4167.328,12638.573,3212.515,3842.885,906.649,446.941,539.674,6952.672,839.042,2021.057,695.813,1684.689,1967.216,,,
158,d268eaa693,2026-09-30,5617,Convert floats with Eisel-Lemire when std::from_chars is unavailable (#5617),1987.608,4086.125,11507.062,3170.013,3830.425,898.856,445.077,542.854,6919.568,839.210,2021.918,666.925,1701.466,1951.211,,,
159,65af260117,2026-09-30,5609,Move instead of deep-copy ordered_json values when an object grows (#5609),1998.981,4134.057,11592.855,3192.779,3863.005,904.702,446.575,539.685,6850.886,840.845,2035.646,680.331,1682.755,1968.744,,,
160,6a8a7735ed,2026-09-30,5614,Do not throw in contains() for an empty array reference token (#5614),2008.447,4144.024,11612.176,3165.468,3842.060,905.045,443.941,539.755,6846.042,846.248,1998.713,669.752,1684.717,1953.487,,,
161,0050d0f7a4,2026-09-30,5637,Share one nesting depth limit between all bounded descents (#5637),2021.078,4170.581,11589.886,3224.963,3937.021,906.411,448.033,541.177,6911.391,848.641,2040.978,670.005,1703.593,1984.639,,,
162,68beba727c,2026-09-30,5679,Fix from_json() for enums with underlying type bool (#5679),1986.468,4139.033,11632.833,3201.351,3798.006,888.464,438.471,535.903,6843.110,836.030,1996.109,685.053,1672.430,1940.598,,,
163,fc4c9c3446,2026-09-30,5680,Fix clear() to also reset the subtype of a binary value (#5680),1972.561,4094.867,11540.157,3155.722,3833.925,893.243,445.764,539.739,6848.562,843.068,2016.293,664.788,1685.759,1965.342,,,
164,678fd3017b,2026-09-30,5681,Fix element path for map/unordered_map JSON_DIAGNOSTICS errors (#5681),2014.783,4164.471,11563.614,3219.865,3891.917,892.727,445.945,542.044,6900.807,844.422,2034.323,669.901,1688.051,1981.601,,,
165,6d7845d207,2026-09-30,5683,Fix deprecated json_pointer/string operator== warning in value() (#5683),1965.197,4105.789,11501.364,3157.544,3800.289,898.122,445.399,539.685,6900.433,834.541,2000.133,652.354,1670.945,1960.876,,,
166,42f89e3130,2026-09-30,5684,Let to_json(std::optional<T>) propagate exceptions from T's to_json (#5684),2016.899,4156.430,11476.489,3216.315,3895.245,908.714,444.300,541.764,6923.422,839.459,2018.934,672.859,1689.306,1987.428,,,
167,6218aa212b,2026-09-30,5687,Throw std::length_error for operator[](SIZE_MAX) instead of corrupting the array (#5687),1989.158,4149.156,11547.229,3193.015,3845.187,905.308,446.389,541.290,6853.266,843.028,2037.245,661.213,1681.390,1966.649,,,
168,1151826508,2026-09-30,5691,Take diff()'s fast path unless the object type reorders members (#5691),1991.280,4147.341,11570.312,3171.182,3847.333,904.510,441.250,539.803,6885.776,836.303,2018.693,665.307,1685.990,1970.057,,,
169,e444a66276,2026-09-30,5693,Copy values before inserting an initializer list into an array (#5693),2000.774,4175.507,11546.979,3189.357,3841.169,897.455,442.384,539.493,6839.688,836.213,2014.519,667.390,1685.418,1968.991,,,
170,bfea6f36d3,2026-09-30,5694,Fix to_msgpack() reading the inactive number union member (#5694),1997.465,4144.279,11549.781,3224.287,3855.120,899.475,441.995,539.924,6903.776,839.550,2019.396,664.487,1688.249,1954.211,,,
171,5b11a0282c,2026-09-30,5697,Exchange the CustomBaseClass subobject in basic_json::swap() (#5697),1987.983,4074.349,11483.114,3174.632,3841.604,893.256,438.279,535.885,6866.641,834.328,1996.396,660.828,1676.300,1936.210,,,
172,44a88d85be,2026-09-30,5698,Fix NLOHMANN_JSON_SERIALIZE_ENUM_STRICT's from_json message (#5698),1972.237,4125.945,11373.917,3158.716,3810.039,890.097,438.075,534.577,6867.432,842.045,2028.150,664.206,1681.353,1936.231,,,
173,bfe0f32d71,2026-09-30,5699,Fix std::terminate and null pointer access in input_stream_adapter (#5699),2014.371,4159.779,11667.416,3200.425,3876.135,911.716,448.788,543.198,6932.657,852.397,2056.197,668.764,1699.573,1984.479,,,
174,4bb1b14b06,2026-09-30,5702,Trim the compiler-appended NUL from wide/UTF string literals too (#5702),1979.723,4105.685,11603.562,3180.932,3846.698,906.188,443.969,534.534,6837.479,840.588,2006.043,654.851,1672.289,1965.408,,,
175,5bd766aa50,2026-09-30,5703,Move to_bson's binary subtype check into calc_bson_sizes (#5703),1999.606,4183.386,11588.646,3192.771,3844.425,900.169,446.795,541.406,6888.114,847.107,2022.637,663.480,1686.702,1974.777,,,
176,6ae17630a4,2026-09-30,5705,"Reject integral keys for contains(), find(), and count() at compile time (#5705)",2000.405,4157.120,11551.656,3197.417,3891.646,903.558,448.544,541.553,6914.203,848.561,2042.578,663.661,1691.910,1974.341,,,
177,7fd6895788,2026-09-30,5706,Hide a discarded container's content from the parser callback (#5706),1971.987,4075.362,11463.219,3164.909,3797.453,889.534,443.974,535.026,6857.323,835.793,2025.343,651.970,1687.670,1951.428,,,
178,66877675b1,2026-09-30,5719,"Check the iterator range for binary values in basic_json(first, last) (#5719)",1970.369,4104.886,11534.635,3168.601,3796.291,897.271,444.655,538.917,6826.990,842.445,2016.962,650.099,1673.940,1953.693,,,
179,2ea6d8c127,2026-09-30,5720,Require the found key to equal the looked-up key when comparing objects (#5720),2015.556,4188.886,11567.125,3251.890,3863.818,903.970,448.691,540.422,6912.255,843.774,2044.479,653.832,1676.634,1951.959,,,
180,67435c9c7e,2026-09-30,5721,Give a deep copy its type only after its container exists (#5721),1994.257,4160.658,11600.553,3218.367,3880.128,900.769,449.260,541.607,6899.448,841.635,2043.909,666.759,1694.646,1974.861,,,
181,6fc0d501f3,2026-09-30,5610,Move the user-defined string literals to <nlohmann/json_literals.hpp> and add JSON_NO_AUTOMATIC_UDLS (#5610),2021.715,4187.888,11647.594,3209.388,3925.060,911.591,450.961,544.303,6975.265,845.109,2049.853,670.295,1697.019,1987.428,,,
182,fdcc569eee,2026-09-30,5692,Use only documented StringType members in json_pointer (#5692),1965.264,4147.273,11378.188,3159.364,3787.758,889.399,447.397,535.062,6809.698,835.116,2015.202,656.241,1689.072,1955.238,,,
183,6a073dbae4,2026-09-30,5695,Give operator>> a strong exception-safety guarantee (#5695),2010.979,4211.982,11698.218,3205.401,3897.172,898.499,445.961,545.225,6898.870,847.042,2051.316,664.716,1706.401,1981.247,,,
184,3b6ae43c53,2026-09-30,5598,Add JSON_DISABLE_TUPLE_REFERENCE_CONVERSION to fix std::tuple conversions (#5598),2025.122,4195.468,11682.199,3204.529,3924.068,904.766,448.209,544.669,7041.276,849.103,2047.488,665.592,1695.987,1984.755,,,
185,7d7055ec50,2026-09-30,5723,Fix stack overflow converting deep values between specializations (#5723),1985.310,4117.099,11457.052,3157.591,3832.175,895.910,442.225,535.237,6864.375,833.653,2001.760,679.826,1674.819,1956.998,,,
186,35802e78d6,2026-09-30,5735,Remove dead Makefile targets; document macro_builder; tidy serve_header (#5735),2004.498,4163.065,11590.594,3184.810,3902.229,906.494,447.394,539.542,6923.969,845.596,2044.457,666.187,1692.019,1977.030,,,
187,c261578431,2026-09-30,5730,Deduplicate binary reader/writer helpers and fix stale comments (#5730),1968.723,4154.789,11441.718,3160.367,3870.578,889.545,443.139,535.314,6850.886,837.281,2024.650,660.842,1691.628,1978.000,,,
188,1d675cdb46,2026-09-30,5733,Fix CI jobs that check less than they claim; move arm64 to GitHub (#5733),1995.704,4206.185,11691.125,3227.622,3966.104,909.748,449.770,541.566,6951.938,852.506,2009.592,663.701,1686.265,1983.285,,,
189,a32f61eb98,2026-09-30,5678,Fix update() and merge_patch() when the argument is *this or one of its members (#5678),2014.810,4157.101,11636.135,3210.326,3924.659,899.344,448.133,541.371,6913.401,841.487,2038.263,667.515,1697.503,1980.686,,,
190,18dd5663b0,2026-10-01,5548,Diff deeply nested values without recursing per nesting level (#5548),1990.931,4152.500,11469.697,3204.740,3985.593,903.248,448.981,540.974,6929.740,847.493,2040.504,665.352,1698.903,1981.438,,,
191,3926fcaac3,2026-10-01,5729,"Deduplicate serializer dump code; fix stale includes, docs, and lint (#5729)",1999.556,4178.489,11581.000,3208.657,3876.755,891.669,452.445,538.525,6893.078,846.721,2042.010,662.154,1689.653,1975.503,,,
192,cff0a61369,2026-10-01,5731,Share DOM SAX position handling; fix stale parser and lexer comments (#5731),2017.231,4112.604,11588.291,3157.047,3890.343,902.329,458.713,539.539,7020.568,847.995,2073.873,654.562,1696.823,1978.381,,,
193,e400780533,2026-10-01,5745,Re-amalgamate single_include (#5745),1980.338,4100.659,11418.854,3166.896,3835.432,885.298,452.886,538.053,6888.203,824.666,2031.410,650.846,1668.952,1949.107,,,
194,6aec1a085f,2026-10-02,5677,Report BON8 input that ends after a UTF-8 lead byte as truncated (#5677),2003.321,4099.066,11614.364,3159.029,3849.857,899.995,459.542,539.436,6904.474,843.221,2071.503,652.303,1685.702,1972.556,,,
195,4d46bce4e1,2026-10-02,5750,Fix CI on develop (#5750),1962.685,4025.677,11277.718,3103.052,3785.213,894.610,448.583,533.887,6870.062,834.856,2020.231,658.339,1674.874,1954.242,,,
196,63c10a51fc,2026-10-02,5638,"Review and extend the documentation, and check it in CI (#5638)",1968.954,4036.851,11425.135,3104.359,3797.852,902.519,451.067,537.668,6910.375,852.438,2043.889,674.938,1701.314,1971.711,,,
197,6d0867a85f,2026-10-02,5751,Make comparisons with scalars noexcept only when the conversion is (#5751),2008.360,4091.453,11376.562,3144.575,3820.110,903.850,455.980,538.035,6851.885,841.549,2010.128,667.182,1690.586,1970.957,,,
198,d11e89471b,2026-10-04,5606,Assert on missing array indices in const operator[] and document the JSON pointer case (#5606),2000.121,4075.695,11475.520,3139.456,3837.211,900.437,453.703,538.895,6921.432,845.064,2027.417,663.969,1679.148,1964.082,,,
199,df27cc3d4c,2026-10-04,5682,Add scalar-on-left overloads for legacy discarded comparisons in C++20 (#5682),2010.838,4092.432,11495.625,3125.726,3873.167,911.281,456.807,538.386,6911.630,844.451,2033.630,688.219,1691.407,1971.697,,,
200,6f2048cd5d,2026-10-04,5685,Accept lvalues in ordered_map::emplace's value parameter (#5685),1999.816,4095.006,11445.740,3136.685,3924.146,918.692,458.336,542.423,6968.520,848.783,2037.096,667.772,1708.274,2002.449,,,
201,0d01d6ae90,2026-10-04,5686,Classify leaves with operator<=> itself past the nesting bound (#5686),1983.320,4116.981,11466.250,3192.969,3923.208,914.596,456.625,539.558,6975.537,849.252,2056.035,701.221,1716.493,1983.908,,,
202,b730946432,2026-10-04,5689,Fix key types convertible to std::string_view breaking lookups (#5689),1990.288,4060.487,11377.709,3107.537,3803.857,892.191,451.727,538.045,6896.480,844.989,2018.884,658.649,1676.566,2023.638,,,
203,49cd427196,2026-10-04,5690,"Copy-construct the base class of a deep copy's elements, not assign it (#5690)",1983.320,4033.156,11333.843,3138.547,3882.878,894.785,454.473,538.337,6918.619,841.205,2072.151,655.193,1693.871,1977.288,,,
204,756b28c2b8,2026-10-04,5696,Keep a NUL byte ending a // comment as the end of input (#5696),1985.931,4099.331,11579.875,3148.560,3872.422,896.276,451.436,536.774,6901.156,845.631,2014.820,648.054,1685.199,1971.762,,,
205,1edf0ef041,2026-10-04,5700,"Fix value(json_pointer, default) aborting under JSON_NOEXCEPTION (#5700)",1987.233,4076.133,11442.625,3124.099,3888.688,898.266,454.349,539.423,6950.140,852.803,2030.279,654.586,1691.751,1978.197,,,
206,a212d3b2e4,2026-10-04,5722,Preserve the object comparator's state in a deep copy past the nesting bound (#5722),2000.138,4113.471,11391.854,3151.006,3866.904,905.695,455.384,539.504,6929.818,842.213,2029.619,674.438,1697.044,1983.856,,,
207,1df1e8a845,2026-10-04,5591,Make cross-string-type basic_json conversion explicit without implicit conversions (#5591),2000.533,4107.994,11370.989,3160.854,3881.635,897.877,455.201,540.307,6927.167,840.130,2053.458,664.118,1697.618,1982.876,,,
208,38a2db260c,2026-10-04,5728,Remove dead metaprogramming and duplicated code in traits and pointers (#5728),1971.450,4040.828,11319.270,3109.521,3819.505,903.606,451.137,538.725,6825.640,843.951,2016.652,663.160,1684.596,1958.896,,,
209,c5650eaa3c,2026-10-04,5704,Reject malformed UTF-16/UTF-32 units in wide-string input (#5704),2006.689,4133.594,11469.209,3180.930,3881.633,902.924,456.572,540.557,6992.385,850.474,2025.267,652.367,1680.025,1957.468,,,
210,40021f38fb,2026-10-04,5589,Add basic_json::as_base_class and document name conflicts with custom base classes (#5589),2012.673,4147.193,11453.250,3167.448,3892.542,910.149,457.238,541.642,6998.084,852.247,2049.759,652.868,1688.229,1972.508,,,
211,73e9eae3c1,2026-10-04,5746,Add an error_handler parameter for UTF-8 to the binary readers and writers (#5746),2013.845,4130.237,11456.041,3135.688,3818.956,892.111,449.408,538.308,6825.213,835.872,1495.468,697.054,1679.760,1970.285,,,
212,d8d47be4a5,2026-10-04,5754,Fix CI on develop after merging the ready-to-merge PRs (#5754),2013.191,4119.948,11573.656,3173.029,3941.703,912.201,459.208,541.264,7013.364,848.908,1514.681,699.273,1685.391,1984.652,,,
213,6b4b825af2,2026-10-04,5607,Handle numbers that do not fit narrow number types in the binary readers (#5607),2009.190,4044.127,11362.677,3127.688,3827.841,892.131,449.386,534.731,6915.360,829.562,1487.640,697.206,1688.237,1952.157,,,
214,8c1f60a45e,2026-10-04,5600,Store maps with enum keys as objects (opt-in) (#5600),2008.560,4128.059,11523.011,3187.763,3843.177,912.520,456.427,537.514,6859.010,839.685,1501.515,696.508,1688.848,1968.910,,,
215,c5a7a4b46d,2026-10-04,5688,"Add deprecated from_bon8/from_bjdata(ptr, len) overloads (#5688)",2030.310,4108.505,11412.907,3141.836,3899.435,904.756,455.298,541.069,6926.151,846.240,1504.193,700.820,1693.983,1987.713,,,
216,23d3b373e1,2026-10-04,5755,Add JSON_DELETE_DEPRECATED_FUNCTIONS to delete the deprecated functions (#5755),2018.708,4106.015,11533.729,3134.945,3826.409,899.623,452.833,538.544,6846.443,830.555,1509.060,705.724,1692.819,1971.476,,,
217,8a142bc436,2026-10-06,5764,"Fix CI on develop after #5600, #5607, and #5755 (#5764)",2017.533,4151.854,11526.334,3195.240,3884.953,907.457,456.697,540.114,6891.136,844.145,1517.241,699.051,1690.344,1972.104,,,
218,5379e04ce4,2026-10-06,5761,Throw type_error.321 when serializing discarded values to binary formats (#5761),1999.156,4055.300,11427.521,3153.581,3836.060,891.927,455.413,540.938,6883.093,853.094,1510.099,701.888,1686.695,1982.806,,,
219,0a365865f9,2026-10-06,5762,Make basic_json destruction allocation-free and non-recursive (#5762),2024.289,4081.646,10719.428,3112.958,3900.503,924.900,462.081,540.765,6965.453,850.019,1511.381,669.802,1620.269,1912.078,,,
220,5ecb704f6b,2026-10-06,5592,Speedup; check for the expected separator before the lexer's token switch (#5592),1920.428,3801.979,10139.250,2891.862,3833.159,823.859,451.951,540.310,6885.672,843.570,1512.778,668.793,1608.501,1885.206,,,
221,6d4543e743,2026-10-06,5767,Fix destroy() for ObjectTypes without reverse iteration (#5767),1929.030,3843.266,10232.541,2911.458,3926.867,830.030,450.002,542.043,6938.890,846.589,1515.211,675.264,1622.245,1904.006,,,
222,9b179cee1e,2026-10-06,5770,Handle all value_t enumerators in has_no_children() (#5770),1931.275,3794.497,10155.125,2891.927,3871.831,829.432,446.176,535.126,6909.625,833.114,1498.945,677.571,1615.785,1884.043,,,
223,69874e4544,2026-10-06,5760,Fix NUL bytes in UBJSON/BJData high-precision numbers (#5760),1924.896,3853.081,10247.750,2926.515,3872.041,835.227,453.025,541.002,6919.037,842.240,1521.169,674.487,1607.441,1880.884,,,
224,162e13b86f,2026-10-06,5758,Add with_*_t alias templates to create basic_json types with changed template parameters (#5758),1938.268,3842.126,10289.968,2914.104,3962.414,834.967,455.536,543.630,6969.266,850.082,1530.064,678.054,1635.303,1916.763,,,
225,21a69230bd,2026-10-06,5585,Create a value before giving it its type (#5585),1918.165,3829.354,10247.656,2914.619,3874.909,832.287,451.252,543.791,6873.995,839.514,1521.088,699.604,1615.742,1894.449,,,
226,ff6f3d7d4a,2026-10-07,5766,Reject nested indefinite-length CBOR string chunks (#5766),1926.074,3868.810,10256.823,2919.802,3957.807,832.129,457.241,543.640,7024.745,847.770,1522.612,705.623,1634.212,1918.402,,,
227,1c754cfe31,2026-10-07,5701,Copy a pair-shaped array value under JSON_BRACE_INIT_COPY_SEMANTICS (#5701),1930.652,3828.195,10263.927,2921.570,3901.404,832.628,455.652,541.701,6909.037,843.563,1512.309,704.354,1623.254,1909.917,,,
228,24dd7c63f0,2026-10-07,5777,Re-amalgamate after #5740 (#5777),1908.632,3833.930,10278.146,2905.443,3935.422,838.465,454.491,545.605,6905.047,839.087,1519.816,709.223,1618.643,1886.706,,,
229,30e542e52a,2026-10-07,5776,Declare the namespace-scope constants in to_chars.hpp inline (#5776),1934.934,3823.724,10229.636,2916.698,3929.565,829.102,452.279,543.038,6951.995,837.059,1524.049,720.722,1619.823,1903.938,,,
230,367336c83d,2026-10-07,5779,Fix CI on develop after #5585 (#5779),1928.921,3780.927,10153.395,2883.604,3877.750,824.488,451.999,543.662,6927.395,835.495,1506.387,694.058,1622.903,1907.732,,,
231,069ace74af,2026-10-07,5707,"Round-trip BJData ND-array annotations exactly (single precision, key order) (#5707)",1937.387,3843.716,10184.302,2923.323,3936.570,827.610,456.123,543.169,6907.756,847.020,1515.229,696.202,1626.001,1901.142,,,
232,43fe8928e1,2026-10-07,5781,Stop binary writers overflowing the stack on deep values (#5781),1961.046,3868.274,10300.573,2899.792,3982.526,845.594,461.395,543.298,7059.093,846.696,1522.728,697.717,1623.846,1921.370,,,
233,a5f5d3059b,2026-10-07,5772,Make std::hash<basic_json> consistent with operator== for numbers (#5772),1949.220,3857.159,10170.427,2890.052,3981.349,840.234,459.334,541.947,6953.786,843.495,1509.713,703.339,1627.086,1911.653,,,
234,a269794db7,2026-10-08,5782,Use MSVC intrinsics for full multiplication (#5782),1931.869,3817.742,10159.666,2902.820,3903.263,840.740,455.827,540.621,6884.562,843.272,1513.776,702.028,1614.459,1901.008,,,
235,69a0c1b82c,2026-10-09,5328,Avoid allocating temporary basic_json for cbor and msgpack object keys (#5328),1909.579,3777.560,10065.682,2852.732,3897.659,833.289,459.856,540.631,6882.354,833.998,1498.288,314.059,1609.343,1906.714,,,
236,374dfe4f0f,2026-10-09,5791,Keep converted object keys alive while writing UBJSON and BJData (#5791),1911.274,3827.188,10159.553,2886.568,3890.388,833.632,459.800,542.649,6954.547,838.507,1509.324,314.357,1613.655,1892.838,,,
237,44e8597701,2026-10-09,5792,Flatten deeply nested values without recursing per nesting level (#5792),1940.103,3811.779,10139.396,2865.050,3874.896,835.001,459.686,544.065,6866.943,836.862,1496.298,314.617,1614.837,1891.741,,,
238,2913e96433,2026-10-09,5793,Unflatten in time and memory linear in the pointer depth (#5793),1908.453,3785.099,10262.147,2878.961,3920.657,845.619,459.806,543.998,6874.813,832.659,1486.901,312.175,1589.620,1863.981,,,
239,84ee12a67c,2026-10-09,5797,Make UTF8_ACCEPT/UTF8_REJECT inline variables to avoid TU-local exposure in modules (#5797),1922.691,3792.849,10162.656,2871.562,3887.719,836.308,456.522,542.577,6912.807,840.369,1497.447,313.683,1609.988,1899.591,,,
240,1649d9eda4,2026-10-11,5783,Use and extend the detail helpers to remove duplicated code (#5783),1916.258,3804.242,10297.344,2913.118,3847.662,836.519,453.270,538.750,6953.015,832.774,1506.068,324.715,1596.974,1875.878,,,
241,2cca04ae6f,2026-10-11,5800,Report one-character non-numeric array indices like longer ones (#5800),1932.327,3803.750,10135.438,2881.041,3894.622,840.016,458.569,538.037,6842.948,829.444,1499.722,324.811,1607.194,1875.851,,,
242,74a03dec84,2026-10-11,5802,Throw type_error.321 for discarded values in to_bon8 (#5802),1924.695,3814.854,10084.239,2873.180,3848.498,839.406,450.575,534.181,6893.005,834.300,1503.369,324.389,1607.323,1887.871,,,
243,e8b747e4bc,2026-10-11,5808,Re-amalgamate single_include after #5795 and #5806 (#5808),1937.995,3840.622,10221.990,2896.024,3885.568,834.394,458.874,539.771,6906.182,839.793,1517.689,324.800,1609.838,1890.885,,,
244,40a62947d3,2026-10-12,4965,support JSON Merge Patch (RFC 7396) diff creation (#4965),1932.021,3822.188,10248.416,2924.560,3980.331,842.462,459.010,540.237,6978.526,838.941,1529.508,326.435,1636.153,1917.472,,,
245,f23830b65e,2026-10-13,5809,Derive the lexer position lazily for seekable input (#5809),1814.075,3368.028,9974.755,2807.532,3943.229,647.639,457.018,551.206,6954.166,843.355,1522.762,315.716,1618.953,1903.816,,,
246,aa9620fb15,2026-10-13,5810,Skip the indentation after a newline 8 bytes at a time (#5810),1719.629,2959.344,10139.771,2799.555,3939.292,592.867,465.821,545.858,6968.068,849.167,1519.774,315.385,1629.981,1907.253,,,
247,e839bbd1c0,2026-10-13,5813,"Export client-facing headers from json.hpp for IWYU / include-cleaner, and check clients in CI (#5813)",1725.742,2949.070,10136.603,2821.591,3919.927,589.957,463.642,544.851,6987.427,843.151,1517.562,314.425,1619.671,1903.613,,,
248,5b4c8f9b00,2026-10-14,5738,"Speed up the lexer: own float parser, string scan, and \u table (#5738)",1615.668,2934.565,8763.651,2794.503,3928.286,559.107,374.921,516.391,6937.140,815.776,1513.238,325.043,1625.226,1912.905,,,
249,91a7a94cc6,2026-10-14,5634,"Write doubles with the shortest digits (Żmij), digits in registers (#5634)",1613.126,2929.599,8708.599,2783.954,3874.248,548.449,363.632,468.127,2421.176,745.466,1511.406,323.743,1614.195,1900.392,,,
250,a6e9785ab6,2026-10-15,5831,Look up the key only once in the callback parser's key() (#5831),1589.309,2938.557,8798.823,2767.872,3882.154,547.301,364.257,467.833,2395.851,744.716,1506.830,316.192,1623.771,1899.458,,,
251,0c4e7c103c,2026-10-15,5834,Make flatten() linear for ordered_json (#5834),1625.754,2936.203,8755.088,2793.081,3879.740,557.529,366.745,468.359,2418.388,746.210,1524.325,315.954,1614.677,1898.544,,,
252,0a4b3a84ee,2026-10-15,5836,"Speed up JSON pointer parsing, formatting, comparison and lookup (#5836)",1622.914,2915.901,8819.073,2783.990,3922.758,558.429,366.216,470.019,2427.606,747.168,1526.881,316.972,1625.611,1912.601,,,
253,6ba53e63dd,2026-10-15,5833,Speed up array-to-container from_json (#5833),1626.155,2920.747,8777.989,2782.870,3988.206,560.154,367.695,469.892,2427.262,749.301,1529.474,316.399,1631.810,1915.217,,,
254,ca7740fef2,2026-10-15,5837,Move elements when converting rvalue containers to JSON (#5837),1615.747,2928.778,8765.792,2773.062,3926.456,561.034,367.498,469.807,2424.344,748.423,1523.215,316.339,1624.374,1894.455,,,
255,4530d9681c,2026-10-15,5832,Fix quadratic parent updates for ordered_json with JSON_DIAGNOSTICS (#5832),1618.937,2911.378,8794.094,2763.191,3886.974,555.789,366.475,469.275,2415.231,746.755,1512.590,315.856,1618.226,1899.284,,,
256,91869983a0,2026-10-15,5840,Make the value lifecycle inline-friendly (#5840),1595.075,2832.274,8420.390,2690.050,3876.841,555.209,366.118,469.783,2424.335,747.931,1485.914,314.048,1549.787,1775.823,,,
257,6a27b9acb2,2026-10-15,5838,Construct remaining hot-path exceptions out of line so core functions inline (#5838),1589.535,2824.360,8466.755,2699.690,3888.990,557.917,364.879,471.601,2422.995,746.543,1498.371,314.978,1539.656,1797.752,,,
258,4f11512641,2026-10-15,5835,"Speed up container destruction, iterator access and diff() (#5835)",1515.750,2714.756,8639.213,2574.698,3805.860,561.827,366.793,469.680,2421.769,748.727,1383.744,317.248,1446.525,1705.789,,,
259,ed86019a21,2026-10-15,5839,Move binary reader error construction out of line (#5839),1507.907,2766.774,8597.870,2622.289,3767.638,553.026,362.644,468.482,2408.731,744.936,1362.080,324.833,1445.531,1703.216,,,
260,6261d1e432,2026-10-15,5842,Construct the JSON Patch exceptions out of line (#5842),1532.015,2756.867,8670.677,2617.989,3869.133,558.865,365.834,469.932,2435.279,750.295,1380.628,327.010,1453.340,1705.232,,,
261,ce28c722bc,2026-10-15,5815,Allow the same type for number_integer_t and number_unsigned_t (#5815),1533.045,2775.807,8543.755,2615.412,3776.721,553.127,365.866,471.174,2433.384,745.309,1372.372,328.405,1452.848,1716.649,,,
262,91b9ee2602,2026-10-15,5829,Update cppcheck to 1.5.2 (Cppcheck 2.20) and fix its new findings (#5829),1516.450,2748.961,8571.521,2599.870,3807.744,557.303,367.220,472.209,2421.389,743.889,1379.405,326.087,1451.926,1710.506,,,
263,dcb96e82fb,2026-10-15,5822,Escape characters below 0x60 from a table straight into the write buffer (#5822),1525.777,2734.963,8524.771,2588.289,3790.726,557.907,360.057,463.574,2430.626,743.382,1375.816,325.308,1439.947,1695.307,,,
264,b41228c227,2026-10-15,5843,Fix AppVeyor failures from the Zmij double writer (#5843),1497.922,2690.614,8406.906,2582.482,3726.195,548.374,352.932,459.663,2398.953,737.639,1347.507,322.827,1429.640,1682.775,,,
265,4da73dc5ff,2026-10-15,5858,Fix compiler warnings on develop from the API performance stack (#5858),1523.138,2731.825,8474.073,2593.149,3782.769,553.758,359.180,462.915,2380.246,739.049,1346.755,324.909,1441.408,1698.043,,,
266,5683f5e024,2026-10-15,5859,Define less_general() only without three-way comparison (#5859),1504.689,2739.172,8603.693,2605.159,3797.057,560.213,358.865,464.429,2423.456,742.207,1374.000,326.702,1447.488,1712.379,,,
267,cd6b428ef0,2026-10-16,5860,Fix CI failures on develop from the API performance stack (#5860),1510.160,2732.695,8564.510,2603.242,3810.518,556.015,362.409,466.047,2437.364,745.153,1377.439,325.753,1444.892,1699.255,,,
268,cc8334113c,2026-10-19,5866,Do not use Qt's keyword macros as identifiers (#5866),1498.858,2732.644,8535.328,2587.258,3787.993,548.267,362.607,464.487,2403.147,735.633,1368.831,323.997,1442.709,1686.963,,,
269,4da932f518,2026-10-19,5828,Make parsing from std::istream and FILE* fast (#5828),1499.289,2723.605,8397.787,2597.237,1956.330,553.182,363.501,458.898,2397.342,733.054,1362.816,320.346,1429.314,1698.294,,,
270,122d718330,2026-10-21,5620,"Add json_document and json_view: node index, parser, and document (#5620)",1520.651,2751.099,8527.135,2588.494,1994.466,560.384,362.257,461.917,2393.611,741.198,1362.167,328.620,1441.211,1691.238,230.700,389.375,976.277
271,43e97b629b,2026-10-21,5622,"Add element access, iteration, values, and JSON pointers to json_view (#5622)",1493.875,2687.307,8383.354,2567.078,1986.311,547.934,353.938,462.380,2400.331,737.098,1374.560,322.012,1445.504,1686.421,231.353,386.679,958.441
272,4c3a3eb5b5,2026-10-21,5624,Add dump() and comparisons to json_view (#5624),1502.926,2714.747,8522.161,2608.565,2001.856,552.014,359.510,462.656,2393.110,732.091,1366.524,324.313,1442.119,1682.564,228.836,393.082,976.976
273,3ff37ead75,2026-10-21,5628,Scan json_view strings with SIMD and index large objects (#5628),1514.580,2728.619,8406.562,2609.758,2041.176,556.017,357.330,462.573,2383.158,733.939,1368.057,324.391,1442.711,1700.884,177.833,367.806,950.071
274,823eee3b59,2026-10-21,5630,"Add editable json_documents: set, push_back, insert, and erase (#5630)",1498.134,2754.810,8537.062,2588.474,1994.441,556.670,353.931,463.646,2392.987,740.023,1357.930,324.129,1441.622,1698.022,181.404,376.470,962.253
275,4971200b54,2026-10-21,5632,Add images of json_documents: save() and load() (#5632),1494.231,2681.211,8425.834,2543.276,1984.849,548.146,354.762,460.440,2414.747,734.679,1363.841,321.349,1421.806,1670.134,177.777,368.631,949.292
276,4155e2938f,2026-10-21,5633,Write json_view's dump() without a call or conversion per token (#5633),1500.247,2712.357,8612.193,2597.211,2012.860,558.559,359.889,462.371,2412.896,739.048,1372.456,324.070,1441.546,1697.571,180.320,371.514,954.088
277,08d7fbb0a1,2026-10-21,5874,Read FILE* input with std::fgetc under MemorySanitizer (#5874),1543.124,2758.211,8565.730,2584.453,2046.255,558.522,358.865,464.542,2421.435,743.715,1374.005,324.687,1462.572,1700.819,180.714,372.601,965.361
278,0cbe95ffa2,2026-10-21,5824,"Speed up writing CBOR and MessagePack, above all integer arrays (#5824)",1501.550,2706.534,8707.120,2584.807,2039.728,551.688,360.692,466.024,2397.182,742.777,1361.847,201.488,1429.223,1682.436,178.641,371.038,946.389
279,bd5227c2ec,2026-10-21,5805,Fix silent wrong results for custom number types (#5805),1511.036,2733.325,8786.406,2588.906,2000.483,553.456,360.458,465.989,2398.381,743.338,1370.524,201.168,1444.051,1701.345,179.776,372.557,954.733
280,e13e976801,2026-10-21,5851,Accumulate number digits while scanning them (#5851),1501.737,2667.570,7762.365,2523.289,1987.518,545.368,359.336,462.056,2407.652,739.226,1368.104,200.632,1440.390,1688.117,178.721,374.278,956.353
281,5e13f834c1,2026-10-21,5852,Copy the text of float tokens only when a SAX handler asks for it (#5852),1512.318,2655.312,7314.354,2515.044,2019.288,547.993,362.038,463.788,2410.262,745.839,1364.898,208.969,1450.422,1713.902,179.198,371.996,968.699
282,e9970066c5,2026-10-21,5853,"Scan strings with SSE2, SSSE3, or NEON (#5853)",1488.705,2654.404,7339.589,2551.050,2015.716,486.719,341.381,475.591,2434.369,756.973,1376.754,208.797,1449.981,1706.044,182.358,379.153,968.355
283,fa37b952df,2026-10-21,5854,Match literals without a stack array and keep parser states in bytes (#5854),1471.894,2619.164,7285.000,2485.883,1949.380,471.534,347.785,475.287,2413.552,751.487,1374.254,207.522,1443.177,1699.611,181.643,377.971,977.268
284,52fecc1fab,2026-10-21,5855,Move object keys into the value when parsing (#5855),1392.599,2628.688,7362.562,2485.293,1882.663,471.968,339.711,473.663,2414.903,751.376,1319.857,200.185,1448.057,1705.675,179.410,371.865,963.306
285,6aefd8c662,2026-10-21,5878,Copy short printable-ASCII strings without starting the scanner (#5878),1399.384,2664.401,7232.557,2535.425,1922.431,470.185,320.230,418.440,2446.082,696.786,1317.889,201.955,1447.217,1701.135,180.860,376.217,968.215
286,7c26e99ac5,2026-10-21,5879,Copy ASCII strings in the view's dump with ensure_ascii (#5879),1361.839,2610.182,7187.115,2471.708,1853.592,464.274,313.821,414.316,2388.840,687.851,1318.253,200.399,1434.986,1697.487,178.601,368.595,947.799
287,3e031b06a5,2026-10-21,5876,"Use standard library helpers where available, with C++11 fallbacks (#5876)",1381.599,2592.122,7336.719,2499.994,1848.434,467.895,315.257,415.788,2430.769,692.250,1311.164,200.424,1444.303,1698.311,180.149,374.484,961.091
288,9bf531436f,2026-10-21,5861,"Speed up flatten(), unflatten(), diff() and patch() (#5861)",1379.301,2613.219,7170.433,2472.628,1853.035,467.161,315.217,412.303,2406.597,683.062,1298.512,198.681,1434.089,1682.912,177.511,368.116,947.255
289,9855db81f3,2026-10-22,5881,Silence macro-to-enum for the endianness macros (#5881),1369.150,2613.547,7209.787,2476.232,1841.347,467.780,316.011,416.187,2415.504,686.920,1304.263,200.868,1441.243,1694.603,178.739,368.123,948.579
290,aa0b371f7c,2026-10-23,5884,"Faster std::istream input: inline get-area path, binary reads, unbuffered streambufs (#5884)",1375.030,2569.362,7218.375,2484.425,1743.476,470.240,319.245,403.750,2436.034,679.759,1319.508,201.531,1443.354,1698.057,180.133,372.206,946.488
291,86d5c56c54,2026-10-23,5886,"Speed up flatten(), unflatten(), diff() and patch() further (#5886)",1386.169,2622.331,7281.551,2495.923,1700.794,472.317,317.282,403.416,2409.097,682.507,1320.319,200.963,1444.908,1697.678,179.138,375.751,954.573
292,dec0e9b749,2026-10-23,5883,"Write strings, scalars and indentation in dump() with fewer calls (#5883)",1383.235,2621.847,7151.412,2491.644,1732.469,473.034,211.016,288.685,2276.953,416.068,1318.490,200.574,1452.099,1701.256,180.064,372.324,960.583
293,6fa14d8f95,2026-10-23,5885,Write binary formats through reserved sink space and number runs (#5885),1366.956,2600.914,7176.994,2465.343,1691.333,462.351,210.662,285.259,2301.553,417.589,1324.173,136.601,1429.240,1687.947,179.319,368.881,962.518
294,0b924f5375,2026-10-23,5887,Split and print JSON pointers in one pass (#5887),1377.526,2597.394,7242.688,2464.445,1739.841,466.382,211.716,288.202,2319.771,418.288,1318.592,138.744,1441.983,1706.639,179.684,372.087,976.078
295,e9c4fe3cdf,2026-10-24,5889,json_view: indented and ensure_ascii dumps through the fast writer (#5889),1393.007,2627.226,7248.287,2491.551,1769.642,469.976,211.665,291.327,2305.655,420.168,1319.431,139.577,1457.965,1712.927,182.274,377.741,983.284
296,dd7686a269,2026-10-24,5888,"json_view: faster reading, indexing and C-stream parsing (#5888)",1382.444,2607.026,7161.365,2472.635,1701.277,468.438,209.963,287.564,2276.329,415.511,1311.194,137.875,1439.700,1696.646,177.624,367.131,977.802
297,9c50bdd140,2026-10-24,5882,Make the DOM parser cheaper per container and per member (#5882),1392.673,2461.082,6068.625,2334.706,1696.950,475.550,209.313,291.776,2300.287,416.349,1317.581,138.194,1441.209,1707.720,178.751,367.339,978.031
298,01139dc192,2026-10-24,5905,Silence an Infer false positive in json_view materialize (#5905),1381.470,2463.013,6078.010,2335.216,1709.088,475.718,211.023,291.212,2275.302,418.098,1320.441,137.572,1443.434,1696.436,175.969,365.658,975.272
299,fe5e401870,2026-10-25,5901,Consolidate duplicated detail helpers and bodies (#5891) (#5901),1395.881,2462.765,6066.698,2327.708,1706.745,474.184,212.683,289.321,2283.842,417.657,1314.153,138.084,1442.796,1696.588,177.144,364.092,961.847
300,3eae5680d6,2026-10-25,5902,"from_json: number-first dispatch for arithmetic types, loop for std::array (#5902)",1397.343,2477.060,6080.864,2340.781,1711.774,481.523,213.618,289.360,2289.503,417.517,1313.541,138.271,1440.822,1695.785,178.731,367.293,983.555
301,2a56afc714,2026-10-25,5916,Fix VS 2015 build of the DOM parser (#5882) (#5916),1373.929,2476.139,6056.797,2341.890,1749.167,482.883,215.107,290.053,2292.495,417.441,1320.640,137.868,1445.227,1702.064,177.912,367.669,984.794
302,d6431a9104,2026-10-26,5918,Throw out_of_range.411 for JSON Patch add into a null parent (#5917) (#5918),1371.635,2445.905,6017.636,2314.178,1696.447,478.134,210.996,287.397,2278.718,414.186,1291.197,137.374,1436.212,1682.197,175.790,361.130,962.070
303,81d66291c5,2026-10-26,5358,Create objects for pointer tokens that cannot be array indices (#5358),1382.909,2465.649,6052.114,2332.556,1711.721,479.927,213.359,289.913,2289.412,417.201,1311.695,137.572,1437.168,1696.302,177.495,367.526,963.924
304,d5da84249f,2026-10-26,5927,"Skip CBOR tags in front of map keys, validate indefinite text chunks, fix CBOR docs (#5927)",1374.553,2476.464,6076.834,2346.075,1744.224,483.375,211.423,291.148,2287.800,420.247,1320.015,137.369,1449.068,1704.785,177.459,365.004,963.908
305,0c3570d44a,2026-10-26,5929,Validate the UBJSON/BJData container type marker for count 0; fix UBJSON docs (#5929),1381.462,2462.578,6055.183,2329.970,1713.086,484.962,210.683,290.024,2260.371,416.895,1319.093,137.782,1453.495,1706.801,177.031,361.025,962.952
306,dc768a7d5d,2026-10-26,5930,Fix BSON binary subtype 0x02 and check the declared document size earlier (#5930),1386.856,2463.400,6054.255,2337.105,1746.441,485.425,214.508,290.954,2314.702,418.769,1325.164,139.255,1452.125,1718.313,179.005,367.327,977.054
307,60107eda3f,2026-10-26,5931,"Read BJData ND-arrays of float16, restrict ND-array char to 0..127, correct BJData docs (#5931)",1389.051,2464.457,6049.084,2336.727,1710.473,483.159,213.007,288.990,2285.073,417.663,1317.537,137.893,1443.301,1697.126,178.706,364.051,962.202
308,731f1b5bfb,2026-10-26,5919,"json_view: view_mode enum instead of bool Editable, node_kind for node::kind (#5919)",1381.664,2428.529,5978.713,2333.485,1746.571,479.163,211.036,288.957,2281.592,416.990,1308.904,137.486,1447.665,1691.427,175.453,363.704,963.371
309,4cdfa6d0f4,2026-10-26,5920,json_view: no save() and load() on big-endian targets (#5920),1390.901,2477.841,6102.474,2337.925,1777.003,485.382,214.373,290.946,2303.147,421.178,1321.976,139.942,1446.726,1704.816,179.928,367.825,976.532
310,5a2819c940,2026-10-26,5921,json_view: one SIMD macro set with the library (#5921),1393.409,2479.841,6073.011,2350.336,1785.087,485.658,214.651,292.044,2304.448,418.026,1326.212,138.942,1468.981,1719.505,179.174,368.704,982.764
311,e5fe4ebdd2,2026-10-26,5922,json_view: from_json() of the macros reads views directly (#5922),1384.612,2467.078,6056.328,2337.309,1742.751,482.554,213.389,289.543,2299.118,417.521,1309.673,138.237,1448.628,1704.550,177.925,365.163,984.351
312,9e67bfa115,2026-10-26,5923,json_view: the library's std conversions read views directly (#5923),1395.103,2482.517,6066.604,2350.538,1751.603,482.504,213.399,290.185,2306.188,420.406,1317.415,138.730,1444.367,1708.720,178.016,369.111,975.875
313,21ec9bd801,2026-10-27,5915,json_view: fewer allocations when parsing small documents (#5915),1388.282,2469.118,6066.495,2340.391,1744.901,478.745,214.934,292.970,2309.264,422.842,1323.237,138.541,1454.151,1707.314,178.058,366.514,958.110
314,2bb2feeef4,2026-10-27,5942,"Fix the red CI on develop (json_view pointer tokens, bson, from_json tests, Infer, IWYU) (#5942)",1391.981,2468.266,6068.495,2335.707,1751.527,482.908,214.285,291.291,2300.453,417.876,1328.089,138.010,1454.934,1701.845,178.250,367.182,964.917
315,78a0687147,2026-10-27,5940,Strong exception guarantee for operator[](json_pointer) (#5940),1379.414,2467.492,6109.136,2335.309,1723.090,480.260,216.197,292.075,2313.798,415.444,1314.530,138.314,1449.629,1698.792,177.628,364.844,965.314
316,candidate,,,develop + open pull requests,1383.171,2465.866,6049.771,2336.394,1725.095,480.882,214.967,292.621,2289.324,418.010,1320.853,137.793,1439.615,1710.333,176.356,364.229,962.166
1 index commit date pr subject parse_twitter parse_citm parse_canada parse_citm_compact parse_twitter_ifstream accept_twitter dump_twitter dump_citm dump_canada dump4_citm from_cbor_twitter to_cbor_twitter copy_destroy_citm equal_citm view_parse_twitter view_parse_citm view_parse_canada
2 0 55f93686c0 2025-04-11 Merge branch 'release/3.12.0' 3571.487 8219.609 17049.073 4366.792 3846.006 2394.213 1441.213 1375.446 7510.989 1917.809 3463.281 695.524 1643.327 1956.891
3 1 1705bfe914 2025-04-11 4727 :bookmark: set version to 3.12.0 (#4727) 3589.331 8245.422 17079.250 4422.711 3894.787 2397.597 1440.546 1377.745 7514.698 1922.371 3498.997 695.559 1655.240 1967.301
4 2 4cca3b9cb2 2025-04-13 4738 Fix warning and add emscripten CI step (#4738) 3559.657 8195.105 17066.291 4373.011 3794.269 2388.900 1419.182 1355.724 7420.703 1912.038 3468.667 664.214 1631.610 1939.475
5 3 96c1b52f1c 2025-04-15 4742 Fix conversion to std::optional (#4742) 3573.838 8157.276 16993.208 4383.656 3858.927 2395.092 1438.169 1372.208 7497.776 1925.481 3482.185 667.895 1633.619 1946.687
6 4 88c92e605c 2025-04-16 4744 Fix compilation failure and warnings with NVHPC (#4744) 3563.149 8039.911 16922.739 4381.927 3768.560 2385.086 1407.564 1345.578 7370.063 1897.474 3462.010 662.955 1623.286 1925.804
7 5 c67d538274 2025-04-17 4749 Fix C4702 warning and extend MSVC CI job (#4749) 3585.422 8251.057 17050.448 4400.542 3896.586 2390.655 1440.391 1371.722 7453.474 1921.277 3478.523 667.911 1636.206 1939.531
8 6 756ca22ec5 2025-04-23 4736 Provide fallback for missing `char8_t` support (#4736) 3559.146 8139.703 17085.114 4387.658 3856.745 2392.849 1424.997 1370.599 7477.537 1907.661 3484.427 665.541 1634.156 1957.401
9 7 6b9199382b 2025-04-27 4763 Add missing header (#4763) 3541.323 8077.761 17011.636 4359.183 3842.380 2396.686 1421.116 1363.737 7431.375 1902.909 3474.250 664.442 1625.644 1934.732
10 8 3b02afb9d9 2025-04-28 4760 Specialize char_traits for std::byte to fix from_msgpack (fixes #4756) (#4760) 3583.070 8198.146 17134.698 4381.743 3899.872 2409.185 1440.233 1380.810 7504.838 1921.781 3500.125 666.078 1657.207 1966.036
11 9 eef76c200e 2025-04-28 4764 Make library work with C++20 modules (#4764) 3528.529 8080.458 16936.656 4330.570 3764.287 2363.848 1407.851 1358.079 7356.239 1897.423 3455.287 665.194 1632.255 1937.675
12 10 dff2b4756c 2025-04-29 4765 fix: BJData size calculation overflow (#4765) 3553.706 8141.375 17047.511 4360.144 3797.070 2389.756 1417.737 1364.718 7454.313 1921.962 3479.878 666.456 1644.760 1944.696
13 11 9110918cf8 2025-05-04 4748 Fix typos (#4748) 3563.682 8176.427 17239.354 4398.055 3891.669 2399.782 1441.669 1387.133 7516.073 1925.323 3483.271 669.348 1647.760 1957.747
14 12 46e7cd3dc2 2025-05-16 4775 Replace deprecated std::is_trivial in C++26 (#4775) 3565.242 8195.396 17135.646 4373.479 3851.604 2392.258 1418.425 1370.958 7464.854 1909.844 3485.046 665.606 1643.155 1952.329
15 13 828c891427 2025-05-16 4786 Extend type_name() to invalid type (#4786) 3549.573 8103.761 17066.198 4359.911 3804.849 2389.121 1428.584 1366.405 7424.838 1914.434 3452.497 667.452 1632.750 1928.324
16 14 4b17f90f65 2025-05-22 4609 Add `ignore_trailing_commas` option (#4609) 3544.662 8132.052 16997.375 4344.592 3825.765 2382.755 1408.435 1367.468 7460.448 1924.522 3434.062 733.089 1631.356 1891.572
17 15 b19f058465 2025-06-01 4802 Encode infinity and NaN as float for MsgPack and CBOR (#4802) 3550.020 8126.438 17350.885 4327.596 3825.419 2389.356 1409.422 1376.649 7363.802 1921.226 3441.081 683.190 1624.144 1886.388
18 16 cf16c5ab9f 2025-06-02 4805 Use binary_t::value_type (#4805) 3551.735 8143.521 17153.291 4309.477 3829.229 2387.640 1428.550 1385.585 7415.271 1932.347 3425.838 657.735 1631.586 1888.954
19 17 d70e46bc65 2025-06-25 4830 :bug: add missing header to input_adapters.hpp (#4830) 3546.448 8157.469 17062.364 4335.300 3805.221 2382.796 1422.863 1382.581 7411.401 1928.676 3433.190 691.842 1632.972 1892.453
20 18 30d27df61c 2025-07-31 4871 Fix CI (#4871) 3570.015 8150.859 17070.625 4330.078 3806.505 2400.329 1434.947 1381.065 7425.718 1931.556 3429.632 656.545 1633.515 1892.916
21 19 efcf9efb4f 2025-08-02 4873 Fixes #4854 Explicitly handle nullptr in sax_parse (#4873) 3520.381 8050.719 16883.042 4331.820 3861.906 2368.069 1408.435 1375.954 7363.651 1898.466 3432.992 653.988 1634.141 1894.948
22 20 4106af8d92 2025-08-20 4896 :rotating_light: suppress cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator (#4896) 3540.599 8175.265 17010.438 4345.182 3866.833 2393.935 1435.100 1389.496 7453.724 1945.791 3433.169 657.446 1638.434 1900.360
23 21 a63795caf1 2025-10-22 4791 :rotating_light: avoid deprecation warning (#4791) 3550.057 8174.646 16983.177 4363.521 3888.336 2393.305 1423.434 1376.334 7469.407 1936.013 3447.279 666.706 1645.354 1903.707
24 22 1cc56b2dcd 2025-10-23 4957 Address CWG issue 2521 (#4957) 3557.396 8119.651 17072.730 4351.881 3834.739 2386.097 1442.100 1393.245 7474.463 1932.315 3446.883 660.187 1638.983 1896.000
25 23 54be9b04f0 2025-10-23 4960 :page_facing_up: update REUSE (#4960) 3554.625 8098.287 17115.219 4324.578 3809.950 2390.791 1424.488 1376.715 7422.828 1913.208 3424.693 659.030 1623.405 1892.756
26 24 29913ca760 2025-10-25 4963 Add char8_t* overload for _json and _json_pointer (#4963) 3544.899 8169.203 17007.844 4353.594 3797.630 2392.108 1423.032 1375.216 7349.787 1909.897 3428.771 655.625 1635.273 1891.018
27 25 515d994acb 2026-01-01 5044 :page_facing_up: adjust year (#5044) 3524.610 8059.521 16949.416 4313.508 3773.750 2364.742 1410.427 1372.988 7382.438 1915.502 3403.159 643.968 1618.972 1884.213
28 26 8f75700141 2026-01-11 4958 support types convertible to string_view as JSON keys (#4958) 3546.757 8142.599 17103.386 4327.739 3825.990 2388.540 1420.515 1379.309 7413.062 1924.540 3433.677 658.266 1628.079 1890.759
29 27 457bc283ff 2026-01-12 5039 fix(cbor): reject overflowing negative integers (#5039) 3508.883 8077.291 16930.011 4305.982 3785.698 2378.693 1425.526 1366.111 7407.042 1929.142 3478.909 657.722 1636.304 1944.681
30 28 e3014f162a 2026-01-13 5052 Fix conversion to std::optional (#5052) 3547.995 8140.052 17010.031 4321.914 3797.807 2385.856 1430.414 1386.202 7407.260 1930.403 3462.213 657.829 1629.579 1932.066
31 29 5ed07097fa 2026-01-13 5050 Fix -Wtautological-constant-out-of-range-compare in serializer (#5050) 3544.136 8180.208 17033.209 4339.591 3799.779 2391.940 1427.870 1387.871 7368.765 1922.321 3454.938 659.367 1630.707 1959.722
32 30 25f48639c7 2026-01-23 5016 Reference tuple from json (#5016) 3563.180 8209.037 17030.969 4388.675 3895.086 2392.088 1430.666 1393.853 7528.567 1934.347 3481.351 677.234 1645.418 1957.591
33 31 f8eee1bb79 2026-02-07 5071 Annotate unreachable comment-scanner switch paths to satisfy C26819 (#5071) 3508.000 8128.750 16958.959 4315.235 3797.237 2371.963 1425.146 1374.867 7453.381 1930.211 3456.508 658.568 1629.188 1909.736
34 32 fd17b0889e 2026-05-08 5139 Remove nullptr safety check from sax_parse functions (#5139) 3544.101 8033.021 16963.292 4334.102 3800.736 2382.583 1419.050 1361.745 7357.073 1907.153 3429.315 657.041 1618.815 1937.829
35 33 62f3b41b30 2026-05-08 5090 fix: treat single-element brace-init as copy/move instead of wrapping in array (#5074) (#5090) 3550.323 8168.713 17060.031 4349.417 3794.110 2380.583 1416.822 1361.182 7369.651 1897.717 3466.731 659.297 1631.463 1941.905
36 34 4fad446897 2026-05-10 5162 docs: add IDs to @requirement tags to fix Doxygen autolinking (#5162) 3545.440 8031.891 17069.448 4324.698 3802.862 2383.513 1422.768 1384.602 7325.776 1917.606 3469.787 659.011 1631.296 1940.370
37 35 a0a4e7cc0b 2026-05-13 5152 Add front methods to json_pointers (implements #4889) (#5152) 3582.898 8215.010 17034.448 4345.515 3891.513 2396.572 1432.733 1395.714 7554.119 1934.008 3484.859 659.298 1642.314 1957.356
38 36 93e49decbd 2026-05-14 5167 Fix incomplete-type error in set_parents with ordered_json (#5167) 3555.224 8147.771 17017.073 4320.846 3831.318 2386.750 1435.840 1385.578 7436.864 1927.483 3466.508 658.409 1632.724 1939.528
39 37 7192763f15 2026-05-14 5163 Fix compile error when using nlohmann ordered_map with WITH_DEFAULT macros (#5163) 3520.675 8039.145 16892.291 4303.448 3769.198 2363.337 1410.030 1364.679 7380.797 1913.285 3437.278 660.130 1630.738 1943.235
40 38 5a05627b1f 2026-05-14 5169 :rotating_light: fix warning (#5169) 3600.555 8160.854 16979.031 4324.070 3887.823 2389.157 1430.983 1387.106 7509.984 1912.601 3473.713 663.279 1652.982 1958.774
41 39 bb5404bb86 2026-05-15 5164 Fix GCC C++20 modules compilation #5103 (#5164) 3543.823 8120.266 17015.395 4349.300 3794.880 2364.178 1414.408 1374.548 7484.218 1920.495 3444.266 699.326 1626.241 1954.688
42 40 b1bb9fce0c 2026-05-15 3929 Fix for printing long doubles bug in dump_float (#3929) 3549.378 8089.891 16934.927 4313.310 3824.802 2386.958 1412.164 1385.425 7417.869 1930.513 3461.151 651.557 1618.735 1944.450
43 41 cba5dc0ed8 2026-05-16 4563 New macros for the named JSON convertor generation (#4563) 3544.657 8168.182 16990.886 4327.688 3806.963 2370.975 1421.629 1390.206 7454.151 1919.284 3452.456 677.413 1623.622 1941.921
44 42 47202c804a 2026-05-18 5171 Add missing overload to ordered_map::find (#5171) 3527.542 8168.312 17141.989 4409.456 3887.378 2397.007 1428.765 1387.033 7495.604 1935.710 3485.088 660.155 1648.977 1951.430
45 43 58cfecf7f7 2026-05-18 5151 Serialize enum (#5151) 3521.302 8100.104 16805.489 4288.463 3763.971 2381.494 1408.713 1383.059 7328.261 1915.202 3440.372 648.726 1617.661 1922.608
46 44 584e6b1cfb 2026-05-22 5187 Fix: update() parent pointers not updated after recursive merge with JSON_DIAGNOSTICS (#5187) 3550.639 8083.463 17055.198 4326.833 3804.257 2381.519 1432.039 1381.986 7377.844 1915.159 3460.750 656.873 1631.527 1940.953
47 45 02dfbea39d 2026-06-17 5209 added explicit instantiations of 'has_from_json' and 'has_to_json' for std_fs::path (#5209) 3552.209 8215.474 17167.760 4338.404 3845.144 2398.026 1425.012 1387.629 7458.614 1931.388 3475.343 658.183 1644.329 1958.324
48 46 fc1df0b7db 2026-06-23 5172 :recycle: remove unnecessary if (#5172) 3562.088 8175.531 17044.042 4336.583 3863.651 2404.695 1425.872 1389.434 7523.855 1914.128 3481.000 653.259 1639.515 1957.649
49 47 c5b2b26fdc 2026-06-29 5217 :memo: fix docs (#5217) 3526.825 8052.307 17000.011 4343.963 3793.412 2388.194 1416.706 1374.177 7361.646 1904.008 3463.919 658.322 1627.765 1921.887
50 48 b7566c6293 2026-06-30 5161 Harden JSON_HAS_RANGES detection for incomplete C++20 ranges implementations (#5161) 3538.995 8071.787 17120.751 4318.797 3772.445 2384.008 1421.440 1385.239 7419.292 1898.929 3431.466 647.948 1602.258 1928.644
51 49 adf78d3a76 2026-06-30 5215 Minor: unique_ptr template resolution workaround for MSVC (#5215) 3550.380 8138.026 17036.802 4366.062 3842.430 2389.536 1426.658 1385.609 7428.787 1915.233 3467.188 658.332 1636.158 1942.556
52 50 272411c5e6 2026-06-30 5218 Overwork project infrastructure (#5218) 3547.487 8087.250 16962.198 4341.969 3793.831 2387.509 1420.888 1381.072 7450.078 1930.003 3466.193 659.676 1631.329 1943.043
53 51 730b57775d 2026-07-01 5222 :bug: avoid assertion in patch (#5222) 3539.912 8169.771 17027.229 4345.151 3790.753 2376.552 1421.263 1386.717 7399.985 1923.237 3455.722 653.609 1630.914 1934.028
54 52 ca49ab6123 2026-07-02 5223 Extend value to arrays when using JSON pointers (#5223) 3550.341 8113.787 16951.313 4346.805 3793.097 2391.224 1409.695 1380.075 7374.073 1926.401 3458.438 659.382 1629.387 1941.306
55 53 8d7e0046f4 2026-07-02 5224 Add std::format and fmt support (#5224) 3546.935 8170.406 16968.927 4346.906 3814.956 2387.612 1424.861 1386.542 7350.765 1900.376 3461.177 662.476 1633.858 1930.434
56 54 31dd15b258 2026-07-02 5221 Fix ambiguous static_cast (#5221) 3551.945 8213.000 17131.271 4373.620 3845.763 2393.074 1438.633 1385.769 7471.146 1927.804 3486.568 662.015 1631.810 1958.901
57 55 eed1587000 2026-07-05 5234 Reconstruct lexer diagnostics lazily for seekable input (#120) (#5234) 3145.909 5311.094 15381.843 4292.961 3851.260 1966.833 1422.598 1365.461 7443.276 1920.467 3467.060 702.832 1637.587 1905.758
58 56 83c87cb9e0 2026-07-05 5233 Read binary strings/blobs in bulk chunks with a memcpy fast path (#5233) 3141.867 5259.485 15454.959 4326.664 3797.198 1987.623 1406.492 1372.765 7424.729 1899.726 2363.895 667.502 1630.097 1888.392
59 57 acf076a677 2026-07-06 5238 Fix ADL leak of nlohmann::detail through basic_json's default base class (#5238) 3152.153 5277.073 15291.407 4338.828 3839.331 1995.524 1429.960 1365.917 7456.776 1907.928 2398.016 670.257 1627.590 1897.997
60 58 c05c5e229b 2026-07-07 5241 Add missing copyright notices to SBOM (#5241) 3147.485 5268.865 15319.584 4321.823 3796.972 1981.167 1432.689 1371.264 7465.416 1918.083 2388.154 667.119 1630.745 1891.583
61 59 366f3d26e5 2026-07-08 5235 Replace snprintf with a branch-free writer for \uXXXX escapes (#5235) 3127.641 5272.302 15425.239 4340.459 3850.357 1997.957 1459.603 1356.461 7509.703 1899.916 2366.966 668.383 1624.981 1889.145
62 60 f8e99e856c 2026-07-09 5248 Fix nvcc CUDA 12.0/12.1 C++20 ranges parse error (#3907) (#5248) 3132.099 5226.375 15164.510 4301.901 3769.651 1967.647 1456.759 1365.810 7530.724 1908.635 2381.610 683.815 1616.699 1879.795
63 61 855f511db4 2026-07-09 5250 Fix stale Clang -Weverything suppression comments; drop -Wno-missing-noreturn (#5250) 3126.792 5208.338 15352.520 4293.596 3800.544 1969.497 1458.601 1329.851 7372.849 1876.404 2368.894 662.173 1603.881 1874.673
64 62 d0a43141ea 2026-07-09 5253 Fix #3868: Remove operator!= to enable P2468R2 rewritten candidate synthesis (#5253) 3165.182 5270.458 15479.031 4302.729 3845.646 1989.231 1474.135 1343.312 7443.282 1887.909 2392.523 670.395 1634.871 1894.474
65 63 b630f5e9c7 2026-07-10 5260 Fix container input_adapter SFINAE for lvalue-only ADL begin/end (#5260) 3128.117 5263.807 15375.677 4330.544 3819.953 1982.196 1454.088 1339.062 7364.683 1877.699 2361.482 666.486 1616.514 1920.626
66 64 c60217e801 2026-07-11 5205 fix: support constructing json from C++20 range views (#4916) (#5205) 3117.539 5206.552 15308.166 4320.513 3798.713 1983.458 1447.072 1350.950 7357.213 1875.632 2340.731 662.905 1633.357 1934.261
67 65 fe2bcc080f 2026-07-11 5266 Custom BinaryType direct assignment (#5266) 3174.528 5284.562 15383.645 4328.120 3895.086 1996.913 1478.427 1355.569 7512.115 1899.236 2398.490 672.118 1642.910 1967.660
68 66 ca76c37650 2026-07-11 5265 Add iterator+sentinel tests and docs for binary deserializers (#5265) 3134.265 5218.021 15352.521 4306.284 3791.612 1967.824 1451.953 1358.685 7508.828 1891.697 2377.848 665.474 1631.495 1934.907
69 67 c197feff81 2026-07-12 5268 Extend memcpy fast path to sized sentinels (e.g. std::counted_iterator) (#5268) 3116.271 5207.146 15415.771 4272.443 3815.851 1984.966 1451.103 1341.093 7328.037 1865.385 2383.169 664.494 1617.967 1915.428
70 68 1c5a953de5 2026-07-19 5276 reject unpaired UTF-16 surrogates in wide-string input (#5276) 3155.360 5299.631 15419.812 4302.089 3853.104 1987.259 1468.653 1349.665 7549.432 1911.365 2457.555 680.311 1653.282 1955.673
71 69 3565f40229 2026-07-20 5284 reject negative UBJSON/BJData string length (#5284) 3170.456 5301.698 15404.416 4351.226 3893.594 1997.034 1470.907 1358.245 7491.480 1909.601 2401.384 671.260 1639.865 1963.899
72 70 9a3ebb9456 2026-07-23 5287 validate BSON document size against the bytes read (#5287) 3157.646 5264.062 15305.271 4338.672 3839.643 1987.196 1461.356 1351.630 7444.791 1890.626 2398.503 665.262 1655.798 1930.268
73 71 8ec98e2c9e 2026-07-27 5313 adding cleanups to bson writer (#5313) 3150.448 5268.948 15445.927 4308.612 3805.005 1989.643 1466.348 1349.591 7326.453 1895.842 2393.278 708.164 1644.025 1946.652
74 72 2e23687092 2026-07-28 5314 to_bson() silently emits corrupt documents when a length exceeds INT32_MAX (#5314) 3146.534 5254.547 15445.250 4304.008 3798.620 1986.260 1459.735 1345.534 7517.651 1903.996 2395.155 674.344 1644.565 1952.682
75 73 868506dcc0 2026-07-30 5335 Fix CBOR half-float assertion bounds (#5335) 3167.086 5267.068 15397.979 4351.011 3883.135 2003.345 1468.939 1360.483 7455.230 1909.055 2406.305 679.942 1643.646 1945.639
76 74 dd24e2dffd 2026-07-30 5332 check all BSON reads and add an EOF check for booleans (#5332) 3138.315 5284.833 15399.166 4310.513 3847.630 1980.682 1464.104 1344.108 7445.146 1901.512 2400.532 670.850 1635.196 1900.946
77 75 fd72ecfc8c 2026-07-31 5301 validate ndarray element types in write_bjdata_ndarray (#5301) 3164.662 5262.141 15399.010 4287.271 3849.318 1988.186 1460.688 1353.767 7458.380 1893.669 2398.485 668.466 1644.018 1921.615
78 76 bc48951128 2026-07-31 5323 Fix UBJSON high-precision floating-point overflow handling (#5323) 3155.628 5289.864 15474.375 4324.253 3888.966 2015.068 1477.846 1354.622 7480.730 1905.566 2415.428 668.997 1641.776 1911.819
79 77 d94cbd99dc 2026-07-31 5274 reject CBOR array/map length equal to the indefinite-length marker (#5274) 3144.041 5272.193 15466.980 4338.735 3848.849 1999.231 1459.129 1358.119 7507.307 1901.807 2394.972 667.016 1635.960 1899.878
80 78 2222d386c9 2026-07-31 5339 fix: check CBOR tagged subtype reads (#5339) 3095.768 5137.792 15064.146 4258.977 3755.229 1965.900 1454.890 1338.066 7399.068 1883.624 2358.193 660.190 1618.172 1939.713
81 79 585929bff9 2026-08-03 5289 Fix Clang deprecation warning for json_pointer operator== with ordered_json (#5289) 3142.341 5259.360 15258.271 4275.479 3807.672 1969.704 1453.688 1337.633 7451.037 1879.447 2364.966 661.560 1635.617 1945.709
82 80 5f121d8c50 2026-08-03 5336 avoid sign extension in char_traits<signed char>::to_int_type (#5336) 3145.000 5264.880 15441.521 4269.632 3796.781 1983.497 1440.810 1325.232 7427.750 1880.047 2361.899 663.772 1621.595 1912.378
83 81 68f0722a19 2026-08-03 5342 remove discarded array from parent object in end_array (#5342) 3161.273 5269.907 15312.469 4335.433 3840.510 1995.965 1465.745 1355.934 7474.901 1895.483 2401.197 657.397 1634.791 1901.902
84 82 dca9d49a33 2026-08-05 5348 reject out-of-range code points in UTF-32 wide-string input (#5348) 3119.753 5210.979 15209.260 4273.984 3799.034 1995.297 1459.456 1342.982 7431.646 1891.478 2370.364 653.618 1633.585 1882.753
85 83 9a091d2b82 2026-08-05 5362 Do not write BJData ndarrays whose size overflows std::size_t (#5362) 3137.381 5257.312 15286.084 4308.500 3805.325 1995.140 1468.138 1354.729 7510.088 1893.036 2384.577 659.394 1628.260 1890.245
86 84 d5647e6a3b 2026-08-05 5355 Resolve the TODO(niels) in get_ubjson_string (#5355) 3121.278 5249.927 15246.011 4292.737 3800.490 1967.087 1443.762 1333.226 7368.953 1862.131 2347.852 644.647 1623.909 1889.958
87 85 bacdabd176 2026-08-05 5361 Fix start_pos() for strings containing escape sequences (#5361) 3114.653 5251.619 15253.907 4331.818 3786.156 1960.676 1442.388 1330.247 7354.724 1863.306 2351.588 650.781 1623.543 1886.671
88 86 1c136a66c4 2026-08-06 5363 Move the CBOR doc block to the function it describes (#5363) 3124.274 5209.615 15411.897 4293.320 3812.156 1982.854 1457.653 1345.680 7422.343 1884.848 2387.050 656.076 1627.620 1878.737
89 87 6285225fd0 2026-08-12 5211 Fix integer comparison bug (#5211) 3159.557 5291.323 15395.395 4329.836 3867.200 1989.476 1456.052 1359.795 7526.860 1879.642 2396.137 659.077 1638.176 1900.416
90 88 b5378e8deb 2026-08-19 5331 Fix CBOR tag handlers not recognizing tags 0-5 and 21-23 (#5331) 3172.476 5239.812 15479.917 4295.539 3871.289 2003.439 1473.447 1343.742 7516.875 1888.412 2400.572 645.588 1641.621 1886.531
91 89 2f025f401e 2026-08-25 5380 Throw other_error.502 when UBJSON use_type is set without use_size (#5380) 3155.873 5190.312 15144.406 4286.388 3793.805 1968.199 1442.240 1340.929 7373.610 1860.543 2370.570 648.906 1631.207 1893.750
92 90 35705d79d8 2026-08-28 5414 Fix update(merge_objects=true) throwing on primitive-to-object merge (#5414) 3169.029 5252.578 15387.292 4340.690 3893.646 1979.616 1472.286 1361.543 7491.302 1903.909 2401.404 659.396 1641.697 1912.409
93 91 137a40b9aa 2026-09-05 5459 Compare integers with floats exactly instead of widening the integer (#5459) 3134.229 5259.349 15404.541 4300.146 3846.646 1992.155 1467.919 1351.774 7467.146 1887.255 2391.467 660.347 1631.735 1891.751
94 92 3c875683a5 2026-09-05 5461 Make diff() linear when an array shrinks (#5461) 3141.068 5259.000 15271.166 4319.659 3797.088 1983.450 1455.354 1354.676 7444.860 1891.687 2389.333 657.163 1632.998 1887.016
95 93 09b6b6b5ba 2026-09-05 5455 Fix to_bjdata() emitting unparsable output when _ArraySize_ is not an array (#5455) 3161.542 5253.047 15311.718 4291.388 3834.264 1992.744 1472.685 1357.680 7409.479 1889.287 2389.501 698.680 1628.237 1888.705
96 94 faa35cc647 2026-09-09 5484 Skip integer conversion in accept()/SAX validation when the value is unused (#5484) 3103.654 5222.453 15458.573 4215.765 3804.320 1935.161 1468.660 1353.499 7452.052 1883.191 2383.524 654.441 1631.700 1885.664
97 95 6d86cc0f6b 2026-09-09 5490 Speed up whitespace skipping in the lexer (#5490) 3181.328 5276.318 15307.312 4262.771 3877.401 1977.062 1465.196 1356.119 7594.177 1906.814 2388.615 684.926 1636.950 1893.526
98 96 c05347dd54 2026-09-09 5475 Undefine the four JSON_HEDLEY_* macros that leak after including json.hpp (#5475) 3147.932 5156.625 15347.990 4217.505 3871.812 1982.807 1458.787 1354.934 7639.328 1879.823 2370.342 674.625 1637.257 1903.903
99 97 d6660cf718 2026-09-09 5485 Route hand-rolled diagnostic pragmas through Hedley (#5485) 3116.151 5215.531 15257.499 4189.979 3835.023 1974.111 1459.363 1342.996 7553.802 1887.698 2379.999 669.934 1635.350 1877.492
100 98 c9477ccf91 2026-09-09 5496 Throw when JSON Patch remove's target path resolves through a primitive or null parent (#5496) 3138.841 5258.401 15315.417 4201.008 3874.682 1967.630 1446.393 1335.060 7542.708 1870.111 2390.141 668.484 1634.138 1886.981
101 99 8c38e270b5 2026-09-09 5497 Reject JSON Patch move when from is a proper prefix of path (#5497) 3183.820 5280.000 15346.969 4222.164 3839.596 1970.753 1470.428 1351.838 7515.344 1895.809 2389.731 673.696 1633.247 1889.546
102 100 a316738cfa 2026-09-09 5471 Add JSON_HEDLEY_WARN_UNUSED_RESULT to the current accept() overloads (#5471) 3175.891 5281.302 15397.062 4240.576 3934.333 1981.765 1475.890 1353.387 7625.104 1896.181 2401.097 669.729 1646.133 1895.638
103 101 c9f1d2d646 2026-09-09 5477 Broaden JSON_HEDLEY_WARN_UNUSED_RESULT coverage to pure query functions (#5477) 3171.706 5286.880 15430.844 4264.242 3880.943 1979.990 1472.289 1357.283 7569.854 1904.026 2407.487 671.673 1641.521 1889.053
104 102 8e26b9d4b3 2026-09-09 5495 Make contains(json_pointer) return false instead of throwing on unrepresentable array-index tokens (#5495) 3163.789 5240.755 15337.698 4226.154 3880.956 1971.912 1475.322 1357.125 7632.281 1904.060 2401.190 678.863 1638.371 1903.385
105 103 b17c272f46 2026-09-09 5472 Reserve capacity in from_json() object conversion when the target container supports it (#5472) 3152.899 5257.645 15401.000 4210.846 3885.123 1989.159 1476.637 1359.851 7639.396 1898.981 2408.243 670.075 1633.528 1894.086
106 104 3e2de32226 2026-09-10 5516 Remove unused iomanip include (#5516) 3141.349 5253.657 15364.074 4203.969 3847.620 1968.422 1455.035 1352.754 7582.494 1882.051 2371.814 663.504 1630.172 1870.223
107 105 d69fb8654d 2026-09-10 5501 Return the parsed value by move from from_cbor() and friends (#5501) 3133.485 5231.662 15309.926 4183.200 3835.662 1971.125 1462.447 1349.563 7479.136 1904.202 1595.991 661.519 1630.278 1883.994
108 106 4a93aa4e2f 2026-09-10 5283 Speed up parsing of contiguous input (numbers, strings, UTF-8) (#5283) 1963.879 4221.308 11609.531 3278.497 3857.880 927.779 1483.726 1357.793 7483.343 1906.916 1481.419 676.438 1643.746 1895.551
109 107 bfb07786cd 2026-09-10 5473 Fix to_bjdata() silently truncating out-of-range _ArrayData_ elements (#5473) 1941.894 4204.971 11726.688 3264.055 3808.784 923.797 1453.071 1351.760 7458.125 1891.470 1473.508 662.164 1633.043 1888.548
110 108 ff80ed3295 2026-09-11 5285 Speed up dump(), and keep it from overflowing the stack (#5285) 1939.289 4175.541 11781.291 3233.302 3816.101 914.071 441.200 540.473 6895.041 852.214 1478.197 656.635 1632.675 1885.303
111 109 da42a627dc 2026-09-11 5449 Stop dump() from heap-allocating its output adapter per call (#5449) 1937.658 4200.966 11639.198 3235.493 3827.695 909.901 448.948 537.008 6909.036 839.027 1479.968 659.210 1643.621 1878.065
112 110 1dc1d09fc6 2026-09-11 5457 Do not search a container for the value the callback rejected (#5457) 1937.459 4140.078 11576.803 3271.838 3845.193 924.316 450.148 539.031 6848.776 844.624 1470.333 671.563 1645.624 1900.347
113 111 fae364db24 2026-09-11 5458 Move the scanned string into the value instead of copying it (#5458) 1986.146 4110.787 11757.157 3150.932 3830.550 918.517 442.629 539.606 6913.104 843.920 1417.037 655.259 1628.224 1892.991
114 112 dd50f0eb16 2026-09-11 5502 Stop CBOR indefinite-length strings from recursing per chunk (#5502) 1987.853 4033.182 11613.834 3116.378 3841.164 915.943 442.366 539.480 6864.130 836.458 1431.035 656.146 1599.574 1885.858
115 113 4bb2de8cc5 2026-09-11 5503 Reject a nested BJData ndarray dimension vector where it is read (#5503) 1981.298 4086.276 11569.240 3141.539 3829.870 923.087 444.038 539.863 6800.724 835.434 1429.637 655.448 1628.999 1879.300
116 114 44f8ec30e9 2026-09-11 5504 Bound UBJSON optimized arrays of a valueless type (#5504) 2005.265 4092.265 11730.198 3130.635 3863.992 925.033 448.222 542.323 6893.078 849.901 1437.855 662.171 1638.306 1896.324
117 115 0dd8ca9023 2026-09-11 5505 Read MessagePack containers without recursing per nesting level (#5505) 2019.983 4105.305 11862.979 3142.581 3891.601 927.092 447.942 543.936 6939.963 845.634 1442.889 656.578 1637.512 1897.815
118 116 91ab3e81f5 2026-09-11 5506 Read CBOR containers and tags without recursing per nesting level (#5506) 1986.334 4039.961 11554.094 3118.761 3783.101 912.504 440.410 534.894 6831.943 834.661 1439.061 655.287 1615.619 1869.912
119 117 a14619b354 2026-09-11 5507 Read UBJSON and BJData containers without recursing per nesting level (#5507) 2011.959 4095.868 11782.688 3135.264 3873.604 926.014 447.638 541.304 6905.838 846.051 1468.512 664.161 1629.083 1898.772
120 118 0452641c18 2026-09-11 5508 Read BSON documents without recursing per nesting level (#5508) 1974.160 4043.887 11662.938 3095.011 3832.744 916.007 439.914 534.149 6904.453 835.615 1450.792 648.298 1616.917 1874.133
121 119 aa391dc0a5 2026-09-11 5520 Fix two develop CI regressions: dump() nodiscard warning and binary-reader const-correctness (#5520) 2003.010 4068.010 11771.364 3137.266 3825.247 924.668 442.416 539.478 6847.083 841.996 1460.659 649.378 1633.738 1885.897
122 120 a50c2537eb 2026-09-12 5476 Reserve capped array capacity in json_sax_dom_parser::start_array() for definite-length binary arrays (#5476) 1986.488 4063.883 11588.333 3077.995 3827.479 908.419 440.959 539.114 6806.177 833.555 1452.851 662.422 1627.995 1915.388
123 121 c0b2878a44 2026-09-13 5493 Swap diagnostic positions in basic_json::swap() (#5493) 2010.881 4081.057 11734.730 3130.919 3882.258 925.490 450.092 542.953 6925.188 848.486 1480.051 698.636 1643.508 1933.941
124 122 1da2f68992 2026-09-14 5522 Only reserve array capacity if the array type supports it (#5522) 1972.122 4048.622 11775.062 3107.938 3803.528 909.385 441.204 535.885 6793.927 842.843 1446.330 658.787 1619.239 1899.164
125 123 6487678bc5 2026-09-15 5464 Fix swap(array_t&)/swap(object_t&) to update parent pointers under JSON_DIAGNOSTICS (#5464) 2023.028 4116.169 11737.438 3165.172 3893.266 924.912 448.959 541.529 6970.438 852.039 1483.231 689.631 1635.240 1937.356
126 124 c72f37a40d 2026-09-15 5443 Support custom object/array types and improve template parameter handling (#5443) 2001.617 4076.547 11666.583 3109.756 3918.206 923.197 450.592 542.266 6901.703 846.558 1468.284 660.116 1641.586 1905.840
127 125 502e9d66f6 2026-09-16 5479 Fix to_bjdata() emitting the Draft-3-only 'B' marker in default Draft-2 mode (#5479) 1970.935 4018.060 11445.500 3079.409 3809.050 910.459 444.217 539.291 6851.407 833.755 1444.697 698.040 1626.601 1889.024
128 126 c41152e620 2026-09-16 5494 Fall back to plain-object encoding when to_bjdata()'s _ArrayType_ annotation is not a string (#5494) 1979.481 4054.688 11734.292 3085.542 3819.351 916.992 445.126 539.870 6853.005 833.190 1457.166 665.391 1629.586 1888.734
129 127 e564136c22 2026-09-22 5465 Make diff() account for member order in ordered_json objects (#5465) 1970.519 4063.744 11605.198 3087.497 3848.867 915.695 447.051 539.711 6835.172 841.402 1452.004 664.560 1640.751 1890.473
130 128 e485441123 2026-09-22 5466 Restore a duplicate key's prior value when the callback rejects its new value (#5466) 2012.920 4099.265 11796.895 3156.818 3913.812 931.464 451.403 541.419 6981.041 846.536 1469.521 704.138 1633.327 1905.709
131 129 a2b19d6158 2026-09-22 5467 Honor allow_exceptions=false for excessive array/object size (out_of_range.408) (#5467) 1996.478 4084.422 11734.208 3129.099 3850.854 923.499 446.555 539.379 6949.427 842.029 1453.166 694.200 1631.133 1888.865
132 130 d2c1a6a272 2026-09-22 5468 Reject array insert(pos, first, last) iterators not pointing into an array (#5468) 1983.767 4066.651 11618.667 3128.505 3848.427 914.900 447.603 541.973 6915.265 844.307 1458.762 677.699 1638.789 1892.443
133 131 0b20b7e622 2026-09-22 5469 Reject MessagePack/BSON binary subtypes that don't fit their wire format (#5469) 2010.548 4097.476 11681.218 3121.010 3866.146 925.619 448.533 540.786 6957.000 843.349 1463.518 658.302 1630.857 1902.522
134 132 1054b2097e 2026-09-23 5286 Speed up binary writing: value-type output sink + byte-swap number encoding (#5286) 1989.739 4101.393 12034.438 3157.240 3853.987 910.115 449.084 555.970 6884.386 864.526 1471.905 656.635 1661.806 1926.233
135 133 ed513715a8 2026-09-24 5534 Document that a NUL byte in the input is treated as end of input (#5534) 2016.236 4104.763 11906.323 3141.138 3936.240 916.611 455.397 562.053 6987.917 871.110 1475.622 657.877 1676.934 1936.557
136 134 56b3ee566c 2026-09-24 5389 Fix stack overflow when copying a deeply nested value (#5387) (#5389) 1998.356 4051.206 11660.865 3101.107 3834.672 910.072 452.943 544.464 6908.974 849.212 1460.691 638.644 1650.749 1914.423
137 135 918da64657 2026-09-24 5542 Keep BJData ndarray annotations that would not survive a round trip as objects (#5542) 2003.009 4042.969 11517.375 3095.122 3815.360 908.444 448.415 539.423 6911.041 840.044 1449.543 671.530 1651.709 1908.408
138 136 8699de3064 2026-09-24 5555 Stop allocating the BJData excluded-marker list per container (#5555) 2001.718 4071.333 11686.427 3122.065 3796.757 900.895 447.123 539.918 6860.765 844.752 1444.435 646.608 1644.943 1879.295
139 137 2e91641de2 2026-09-24 5544 Test JSON_BRACE_INIT_COPY_SEMANTICS for real, and fix one-element tuples under it (#5544) 2004.785 4083.914 11662.270 3119.602 3917.914 922.465 454.869 547.631 6987.234 853.010 1469.612 649.946 1672.246 1913.098
140 138 7c90ec2323 2026-09-24 5546 Hash deeply nested values without recursing per nesting level (#5546) 1952.912 4071.159 11594.927 3117.497 3793.052 900.729 444.245 539.787 6854.406 841.264 1457.530 643.139 1638.578 1890.482
141 139 4daca40d7b 2026-09-24 5547 Merge deeply nested objects without recursing per nesting level (#5547) 2008.226 4104.399 11619.542 3148.604 3918.175 921.207 457.191 547.553 6942.265 855.352 1464.974 651.924 1665.232 1915.869
142 140 01b53c8c15 2026-09-25 5552 Keep JSON_DIAGNOSTICS parent pointers of ordered_json members after erase() and update() (#5552) 1979.354 4061.378 11603.480 3098.586 3875.258 919.125 455.911 546.269 6940.026 849.511 1461.751 648.841 1660.978 1917.254
143 141 abbe52d6de 2026-09-25 5344 Add JSON_PRECISE_STREAM_POSITION to leave the character that terminates a number in the stream (#5344) 2001.170 4081.617 11653.531 3131.331 3876.208 915.153 453.436 546.720 6971.864 848.900 1463.182 647.946 1662.943 1906.246
144 142 02dd3e67f2 2026-09-25 5390 Fix stack overflow and exponential runtime when comparing nested values (#5390) 1987.861 4074.039 11596.000 3161.284 3901.497 919.541 447.553 543.948 6910.162 845.668 1455.759 664.224 1652.074 1930.575
145 143 465407f3ce 2026-09-25 2818 Improve error message for const fields (#2818) 1975.274 4118.565 11863.448 3130.541 3880.764 910.767 452.904 545.363 6906.890 843.118 1459.728 645.770 1654.265 1934.900
146 144 632a5812a8 2026-09-25 5272 Support zero-member types in NLOHMANN_DEFINE_TYPE_* macros (#4041) (#5272) 1963.323 4021.526 11747.959 3102.006 3784.896 904.545 444.355 543.748 6840.604 841.416 1438.306 639.223 1649.816 1930.274
147 145 d19f7f5dce 2026-09-25 5185 Fix BSON conformance issue (#5185) 1958.606 4048.536 11541.011 3086.805 3817.875 900.452 446.001 544.071 6824.323 837.078 1971.245 641.271 1651.209 1934.647
148 146 c60a0bc336 2026-09-25 5573 Allocate the deep copy's key scratch space with the provided allocator (#5573) 1965.216 4021.459 11630.855 3074.078 3807.258 902.782 444.394 542.562 6919.969 840.942 1975.668 645.827 1637.429 1918.607
149 147 1e44262091 2026-09-25 5560 Make JSON_STRICT_NUL_HANDLING part of the ABI tag (#5560) 1961.862 4069.617 11594.083 3117.500 3817.758 909.186 448.820 544.420 6845.802 844.016 1977.909 645.864 1651.269 1937.217
150 148 95e9a5931c 2026-09-25 5553 Write BSON in linear time, without recursing per nesting level (#5553) 1965.832 4033.394 11589.364 3120.422 3792.091 905.110 446.984 543.328 6794.244 844.943 1991.659 640.188 1647.675 1928.562
151 149 fe4a544c7e 2026-09-27 5515 handled when size exceed uint32 (#5515) 1998.244 4047.208 11755.209 3091.776 3815.000 908.733 447.990 546.295 6903.084 850.946 1993.351 645.487 1654.343 1933.385
152 150 4fa95d9810 2026-09-27 5583 Remove unreachable branches from the binary writer (#5583) 1983.323 4038.331 11666.480 3092.841 3844.935 910.149 449.697 541.110 6840.583 830.604 1979.750 653.542 1650.670 1928.883
153 151 6178982b8d 2026-09-27 5582 Compare unordered objects by key below the nesting bound (#5582) 1971.706 4073.498 11600.646 3132.700 3830.323 910.231 448.982 538.812 6836.770 846.149 2007.607 657.180 1653.089 1934.675
154 152 f7972970a4 2026-09-27 5584 Throw instead of writing MessagePack lengths beyond UINT32_MAX (#5584) 1969.417 4013.021 11602.447 3083.552 3842.495 904.223 447.444 542.170 6862.735 839.628 2000.766 655.034 1653.006 1939.922
155 153 6bd106893a 2026-09-27 5559 Fix CBOR tag handling in cbor_tag_handler_t::store for non-binary items (#5559) 1969.250 4034.693 11691.500 3119.171 3827.860 916.053 455.026 542.577 6886.360 839.718 2012.919 653.031 1651.090 1931.698
156 154 1e101ecac1 2026-09-27 2998 Add BON8 support (#2998) 1975.804 4082.375 11658.542 3192.828 3758.141 907.029 444.920 556.470 6844.698 849.276 1977.153 649.181 1645.306 1920.836
157 155 9e1a09eec0 2026-09-28 5594 Name the key type when rejecting non-string CBOR/MessagePack map keys (#5594) 2006.582 4151.784 11788.532 3156.156 3845.052 915.647 454.027 557.846 6814.282 864.094 2021.072 654.095 1663.051 1947.078
158 156 fc03b9912e 2026-09-28 5597 Look up the locale decimal point at conversion time, not lexer construction (#5597) 2020.431 4172.916 12716.958 3196.958 3909.774 910.001 449.314 547.334 6900.968 852.306 2048.019 665.843 1696.937 1982.586
159 157 5b9ffae8bb 2026-09-30 5616 Move the float conversion chain out of the lexer (#5616) 1992.332 4167.328 12638.573 3212.515 3842.885 906.649 446.941 539.674 6952.672 839.042 2021.057 695.813 1684.689 1967.216
160 158 d268eaa693 2026-09-30 5617 Convert floats with Eisel-Lemire when std::from_chars is unavailable (#5617) 1987.608 4086.125 11507.062 3170.013 3830.425 898.856 445.077 542.854 6919.568 839.210 2021.918 666.925 1701.466 1951.211
161 159 65af260117 2026-09-30 5609 Move instead of deep-copy ordered_json values when an object grows (#5609) 1998.981 4134.057 11592.855 3192.779 3863.005 904.702 446.575 539.685 6850.886 840.845 2035.646 680.331 1682.755 1968.744
162 160 6a8a7735ed 2026-09-30 5614 Do not throw in contains() for an empty array reference token (#5614) 2008.447 4144.024 11612.176 3165.468 3842.060 905.045 443.941 539.755 6846.042 846.248 1998.713 669.752 1684.717 1953.487
163 161 0050d0f7a4 2026-09-30 5637 Share one nesting depth limit between all bounded descents (#5637) 2021.078 4170.581 11589.886 3224.963 3937.021 906.411 448.033 541.177 6911.391 848.641 2040.978 670.005 1703.593 1984.639
164 162 68beba727c 2026-09-30 5679 Fix from_json() for enums with underlying type bool (#5679) 1986.468 4139.033 11632.833 3201.351 3798.006 888.464 438.471 535.903 6843.110 836.030 1996.109 685.053 1672.430 1940.598
165 163 fc4c9c3446 2026-09-30 5680 Fix clear() to also reset the subtype of a binary value (#5680) 1972.561 4094.867 11540.157 3155.722 3833.925 893.243 445.764 539.739 6848.562 843.068 2016.293 664.788 1685.759 1965.342
166 164 678fd3017b 2026-09-30 5681 Fix element path for map/unordered_map JSON_DIAGNOSTICS errors (#5681) 2014.783 4164.471 11563.614 3219.865 3891.917 892.727 445.945 542.044 6900.807 844.422 2034.323 669.901 1688.051 1981.601
167 165 6d7845d207 2026-09-30 5683 Fix deprecated json_pointer/string operator== warning in value() (#5683) 1965.197 4105.789 11501.364 3157.544 3800.289 898.122 445.399 539.685 6900.433 834.541 2000.133 652.354 1670.945 1960.876
168 166 42f89e3130 2026-09-30 5684 Let to_json(std::optional<T>) propagate exceptions from T's to_json (#5684) 2016.899 4156.430 11476.489 3216.315 3895.245 908.714 444.300 541.764 6923.422 839.459 2018.934 672.859 1689.306 1987.428
169 167 6218aa212b 2026-09-30 5687 Throw std::length_error for operator[](SIZE_MAX) instead of corrupting the array (#5687) 1989.158 4149.156 11547.229 3193.015 3845.187 905.308 446.389 541.290 6853.266 843.028 2037.245 661.213 1681.390 1966.649
170 168 1151826508 2026-09-30 5691 Take diff()'s fast path unless the object type reorders members (#5691) 1991.280 4147.341 11570.312 3171.182 3847.333 904.510 441.250 539.803 6885.776 836.303 2018.693 665.307 1685.990 1970.057
171 169 e444a66276 2026-09-30 5693 Copy values before inserting an initializer list into an array (#5693) 2000.774 4175.507 11546.979 3189.357 3841.169 897.455 442.384 539.493 6839.688 836.213 2014.519 667.390 1685.418 1968.991
172 170 bfea6f36d3 2026-09-30 5694 Fix to_msgpack() reading the inactive number union member (#5694) 1997.465 4144.279 11549.781 3224.287 3855.120 899.475 441.995 539.924 6903.776 839.550 2019.396 664.487 1688.249 1954.211
173 171 5b11a0282c 2026-09-30 5697 Exchange the CustomBaseClass subobject in basic_json::swap() (#5697) 1987.983 4074.349 11483.114 3174.632 3841.604 893.256 438.279 535.885 6866.641 834.328 1996.396 660.828 1676.300 1936.210
174 172 44a88d85be 2026-09-30 5698 Fix NLOHMANN_JSON_SERIALIZE_ENUM_STRICT's from_json message (#5698) 1972.237 4125.945 11373.917 3158.716 3810.039 890.097 438.075 534.577 6867.432 842.045 2028.150 664.206 1681.353 1936.231
175 173 bfe0f32d71 2026-09-30 5699 Fix std::terminate and null pointer access in input_stream_adapter (#5699) 2014.371 4159.779 11667.416 3200.425 3876.135 911.716 448.788 543.198 6932.657 852.397 2056.197 668.764 1699.573 1984.479
176 174 4bb1b14b06 2026-09-30 5702 Trim the compiler-appended NUL from wide/UTF string literals too (#5702) 1979.723 4105.685 11603.562 3180.932 3846.698 906.188 443.969 534.534 6837.479 840.588 2006.043 654.851 1672.289 1965.408
177 175 5bd766aa50 2026-09-30 5703 Move to_bson's binary subtype check into calc_bson_sizes (#5703) 1999.606 4183.386 11588.646 3192.771 3844.425 900.169 446.795 541.406 6888.114 847.107 2022.637 663.480 1686.702 1974.777
178 176 6ae17630a4 2026-09-30 5705 Reject integral keys for contains(), find(), and count() at compile time (#5705) 2000.405 4157.120 11551.656 3197.417 3891.646 903.558 448.544 541.553 6914.203 848.561 2042.578 663.661 1691.910 1974.341
179 177 7fd6895788 2026-09-30 5706 Hide a discarded container's content from the parser callback (#5706) 1971.987 4075.362 11463.219 3164.909 3797.453 889.534 443.974 535.026 6857.323 835.793 2025.343 651.970 1687.670 1951.428
180 178 66877675b1 2026-09-30 5719 Check the iterator range for binary values in basic_json(first, last) (#5719) 1970.369 4104.886 11534.635 3168.601 3796.291 897.271 444.655 538.917 6826.990 842.445 2016.962 650.099 1673.940 1953.693
181 179 2ea6d8c127 2026-09-30 5720 Require the found key to equal the looked-up key when comparing objects (#5720) 2015.556 4188.886 11567.125 3251.890 3863.818 903.970 448.691 540.422 6912.255 843.774 2044.479 653.832 1676.634 1951.959
182 180 67435c9c7e 2026-09-30 5721 Give a deep copy its type only after its container exists (#5721) 1994.257 4160.658 11600.553 3218.367 3880.128 900.769 449.260 541.607 6899.448 841.635 2043.909 666.759 1694.646 1974.861
183 181 6fc0d501f3 2026-09-30 5610 Move the user-defined string literals to <nlohmann/json_literals.hpp> and add JSON_NO_AUTOMATIC_UDLS (#5610) 2021.715 4187.888 11647.594 3209.388 3925.060 911.591 450.961 544.303 6975.265 845.109 2049.853 670.295 1697.019 1987.428
184 182 fdcc569eee 2026-09-30 5692 Use only documented StringType members in json_pointer (#5692) 1965.264 4147.273 11378.188 3159.364 3787.758 889.399 447.397 535.062 6809.698 835.116 2015.202 656.241 1689.072 1955.238
185 183 6a073dbae4 2026-09-30 5695 Give operator>> a strong exception-safety guarantee (#5695) 2010.979 4211.982 11698.218 3205.401 3897.172 898.499 445.961 545.225 6898.870 847.042 2051.316 664.716 1706.401 1981.247
186 184 3b6ae43c53 2026-09-30 5598 Add JSON_DISABLE_TUPLE_REFERENCE_CONVERSION to fix std::tuple conversions (#5598) 2025.122 4195.468 11682.199 3204.529 3924.068 904.766 448.209 544.669 7041.276 849.103 2047.488 665.592 1695.987 1984.755
187 185 7d7055ec50 2026-09-30 5723 Fix stack overflow converting deep values between specializations (#5723) 1985.310 4117.099 11457.052 3157.591 3832.175 895.910 442.225 535.237 6864.375 833.653 2001.760 679.826 1674.819 1956.998
188 186 35802e78d6 2026-09-30 5735 Remove dead Makefile targets; document macro_builder; tidy serve_header (#5735) 2004.498 4163.065 11590.594 3184.810 3902.229 906.494 447.394 539.542 6923.969 845.596 2044.457 666.187 1692.019 1977.030
189 187 c261578431 2026-09-30 5730 Deduplicate binary reader/writer helpers and fix stale comments (#5730) 1968.723 4154.789 11441.718 3160.367 3870.578 889.545 443.139 535.314 6850.886 837.281 2024.650 660.842 1691.628 1978.000
190 188 1d675cdb46 2026-09-30 5733 Fix CI jobs that check less than they claim; move arm64 to GitHub (#5733) 1995.704 4206.185 11691.125 3227.622 3966.104 909.748 449.770 541.566 6951.938 852.506 2009.592 663.701 1686.265 1983.285
191 189 a32f61eb98 2026-09-30 5678 Fix update() and merge_patch() when the argument is *this or one of its members (#5678) 2014.810 4157.101 11636.135 3210.326 3924.659 899.344 448.133 541.371 6913.401 841.487 2038.263 667.515 1697.503 1980.686
192 190 18dd5663b0 2026-10-01 5548 Diff deeply nested values without recursing per nesting level (#5548) 1990.931 4152.500 11469.697 3204.740 3985.593 903.248 448.981 540.974 6929.740 847.493 2040.504 665.352 1698.903 1981.438
193 191 3926fcaac3 2026-10-01 5729 Deduplicate serializer dump code; fix stale includes, docs, and lint (#5729) 1999.556 4178.489 11581.000 3208.657 3876.755 891.669 452.445 538.525 6893.078 846.721 2042.010 662.154 1689.653 1975.503
194 192 cff0a61369 2026-10-01 5731 Share DOM SAX position handling; fix stale parser and lexer comments (#5731) 2017.231 4112.604 11588.291 3157.047 3890.343 902.329 458.713 539.539 7020.568 847.995 2073.873 654.562 1696.823 1978.381
195 193 e400780533 2026-10-01 5745 Re-amalgamate single_include (#5745) 1980.338 4100.659 11418.854 3166.896 3835.432 885.298 452.886 538.053 6888.203 824.666 2031.410 650.846 1668.952 1949.107
196 194 6aec1a085f 2026-10-02 5677 Report BON8 input that ends after a UTF-8 lead byte as truncated (#5677) 2003.321 4099.066 11614.364 3159.029 3849.857 899.995 459.542 539.436 6904.474 843.221 2071.503 652.303 1685.702 1972.556
197 195 4d46bce4e1 2026-10-02 5750 Fix CI on develop (#5750) 1962.685 4025.677 11277.718 3103.052 3785.213 894.610 448.583 533.887 6870.062 834.856 2020.231 658.339 1674.874 1954.242
198 196 63c10a51fc 2026-10-02 5638 Review and extend the documentation, and check it in CI (#5638) 1968.954 4036.851 11425.135 3104.359 3797.852 902.519 451.067 537.668 6910.375 852.438 2043.889 674.938 1701.314 1971.711
199 197 6d0867a85f 2026-10-02 5751 Make comparisons with scalars noexcept only when the conversion is (#5751) 2008.360 4091.453 11376.562 3144.575 3820.110 903.850 455.980 538.035 6851.885 841.549 2010.128 667.182 1690.586 1970.957
200 198 d11e89471b 2026-10-04 5606 Assert on missing array indices in const operator[] and document the JSON pointer case (#5606) 2000.121 4075.695 11475.520 3139.456 3837.211 900.437 453.703 538.895 6921.432 845.064 2027.417 663.969 1679.148 1964.082
201 199 df27cc3d4c 2026-10-04 5682 Add scalar-on-left overloads for legacy discarded comparisons in C++20 (#5682) 2010.838 4092.432 11495.625 3125.726 3873.167 911.281 456.807 538.386 6911.630 844.451 2033.630 688.219 1691.407 1971.697
202 200 6f2048cd5d 2026-10-04 5685 Accept lvalues in ordered_map::emplace's value parameter (#5685) 1999.816 4095.006 11445.740 3136.685 3924.146 918.692 458.336 542.423 6968.520 848.783 2037.096 667.772 1708.274 2002.449
203 201 0d01d6ae90 2026-10-04 5686 Classify leaves with operator<=> itself past the nesting bound (#5686) 1983.320 4116.981 11466.250 3192.969 3923.208 914.596 456.625 539.558 6975.537 849.252 2056.035 701.221 1716.493 1983.908
204 202 b730946432 2026-10-04 5689 Fix key types convertible to std::string_view breaking lookups (#5689) 1990.288 4060.487 11377.709 3107.537 3803.857 892.191 451.727 538.045 6896.480 844.989 2018.884 658.649 1676.566 2023.638
205 203 49cd427196 2026-10-04 5690 Copy-construct the base class of a deep copy's elements, not assign it (#5690) 1983.320 4033.156 11333.843 3138.547 3882.878 894.785 454.473 538.337 6918.619 841.205 2072.151 655.193 1693.871 1977.288
206 204 756b28c2b8 2026-10-04 5696 Keep a NUL byte ending a // comment as the end of input (#5696) 1985.931 4099.331 11579.875 3148.560 3872.422 896.276 451.436 536.774 6901.156 845.631 2014.820 648.054 1685.199 1971.762
207 205 1edf0ef041 2026-10-04 5700 Fix value(json_pointer, default) aborting under JSON_NOEXCEPTION (#5700) 1987.233 4076.133 11442.625 3124.099 3888.688 898.266 454.349 539.423 6950.140 852.803 2030.279 654.586 1691.751 1978.197
208 206 a212d3b2e4 2026-10-04 5722 Preserve the object comparator's state in a deep copy past the nesting bound (#5722) 2000.138 4113.471 11391.854 3151.006 3866.904 905.695 455.384 539.504 6929.818 842.213 2029.619 674.438 1697.044 1983.856
209 207 1df1e8a845 2026-10-04 5591 Make cross-string-type basic_json conversion explicit without implicit conversions (#5591) 2000.533 4107.994 11370.989 3160.854 3881.635 897.877 455.201 540.307 6927.167 840.130 2053.458 664.118 1697.618 1982.876
210 208 38a2db260c 2026-10-04 5728 Remove dead metaprogramming and duplicated code in traits and pointers (#5728) 1971.450 4040.828 11319.270 3109.521 3819.505 903.606 451.137 538.725 6825.640 843.951 2016.652 663.160 1684.596 1958.896
211 209 c5650eaa3c 2026-10-04 5704 Reject malformed UTF-16/UTF-32 units in wide-string input (#5704) 2006.689 4133.594 11469.209 3180.930 3881.633 902.924 456.572 540.557 6992.385 850.474 2025.267 652.367 1680.025 1957.468
212 210 40021f38fb 2026-10-04 5589 Add basic_json::as_base_class and document name conflicts with custom base classes (#5589) 2012.673 4147.193 11453.250 3167.448 3892.542 910.149 457.238 541.642 6998.084 852.247 2049.759 652.868 1688.229 1972.508
213 211 73e9eae3c1 2026-10-04 5746 Add an error_handler parameter for UTF-8 to the binary readers and writers (#5746) 2013.845 4130.237 11456.041 3135.688 3818.956 892.111 449.408 538.308 6825.213 835.872 1495.468 697.054 1679.760 1970.285
214 212 d8d47be4a5 2026-10-04 5754 Fix CI on develop after merging the ready-to-merge PRs (#5754) 2013.191 4119.948 11573.656 3173.029 3941.703 912.201 459.208 541.264 7013.364 848.908 1514.681 699.273 1685.391 1984.652
215 213 6b4b825af2 2026-10-04 5607 Handle numbers that do not fit narrow number types in the binary readers (#5607) 2009.190 4044.127 11362.677 3127.688 3827.841 892.131 449.386 534.731 6915.360 829.562 1487.640 697.206 1688.237 1952.157
216 214 8c1f60a45e 2026-10-04 5600 Store maps with enum keys as objects (opt-in) (#5600) 2008.560 4128.059 11523.011 3187.763 3843.177 912.520 456.427 537.514 6859.010 839.685 1501.515 696.508 1688.848 1968.910
217 215 c5a7a4b46d 2026-10-04 5688 Add deprecated from_bon8/from_bjdata(ptr, len) overloads (#5688) 2030.310 4108.505 11412.907 3141.836 3899.435 904.756 455.298 541.069 6926.151 846.240 1504.193 700.820 1693.983 1987.713
218 216 23d3b373e1 2026-10-04 5755 Add JSON_DELETE_DEPRECATED_FUNCTIONS to delete the deprecated functions (#5755) 2018.708 4106.015 11533.729 3134.945 3826.409 899.623 452.833 538.544 6846.443 830.555 1509.060 705.724 1692.819 1971.476
219 217 8a142bc436 2026-10-06 5764 Fix CI on develop after #5600, #5607, and #5755 (#5764) 2017.533 4151.854 11526.334 3195.240 3884.953 907.457 456.697 540.114 6891.136 844.145 1517.241 699.051 1690.344 1972.104
220 218 5379e04ce4 2026-10-06 5761 Throw type_error.321 when serializing discarded values to binary formats (#5761) 1999.156 4055.300 11427.521 3153.581 3836.060 891.927 455.413 540.938 6883.093 853.094 1510.099 701.888 1686.695 1982.806
221 219 0a365865f9 2026-10-06 5762 Make basic_json destruction allocation-free and non-recursive (#5762) 2024.289 4081.646 10719.428 3112.958 3900.503 924.900 462.081 540.765 6965.453 850.019 1511.381 669.802 1620.269 1912.078
222 220 5ecb704f6b 2026-10-06 5592 Speedup; check for the expected separator before the lexer's token switch (#5592) 1920.428 3801.979 10139.250 2891.862 3833.159 823.859 451.951 540.310 6885.672 843.570 1512.778 668.793 1608.501 1885.206
223 221 6d4543e743 2026-10-06 5767 Fix destroy() for ObjectTypes without reverse iteration (#5767) 1929.030 3843.266 10232.541 2911.458 3926.867 830.030 450.002 542.043 6938.890 846.589 1515.211 675.264 1622.245 1904.006
224 222 9b179cee1e 2026-10-06 5770 Handle all value_t enumerators in has_no_children() (#5770) 1931.275 3794.497 10155.125 2891.927 3871.831 829.432 446.176 535.126 6909.625 833.114 1498.945 677.571 1615.785 1884.043
225 223 69874e4544 2026-10-06 5760 Fix NUL bytes in UBJSON/BJData high-precision numbers (#5760) 1924.896 3853.081 10247.750 2926.515 3872.041 835.227 453.025 541.002 6919.037 842.240 1521.169 674.487 1607.441 1880.884
226 224 162e13b86f 2026-10-06 5758 Add with_*_t alias templates to create basic_json types with changed template parameters (#5758) 1938.268 3842.126 10289.968 2914.104 3962.414 834.967 455.536 543.630 6969.266 850.082 1530.064 678.054 1635.303 1916.763
227 225 21a69230bd 2026-10-06 5585 Create a value before giving it its type (#5585) 1918.165 3829.354 10247.656 2914.619 3874.909 832.287 451.252 543.791 6873.995 839.514 1521.088 699.604 1615.742 1894.449
228 226 ff6f3d7d4a 2026-10-07 5766 Reject nested indefinite-length CBOR string chunks (#5766) 1926.074 3868.810 10256.823 2919.802 3957.807 832.129 457.241 543.640 7024.745 847.770 1522.612 705.623 1634.212 1918.402
229 227 1c754cfe31 2026-10-07 5701 Copy a pair-shaped array value under JSON_BRACE_INIT_COPY_SEMANTICS (#5701) 1930.652 3828.195 10263.927 2921.570 3901.404 832.628 455.652 541.701 6909.037 843.563 1512.309 704.354 1623.254 1909.917
230 228 24dd7c63f0 2026-10-07 5777 Re-amalgamate after #5740 (#5777) 1908.632 3833.930 10278.146 2905.443 3935.422 838.465 454.491 545.605 6905.047 839.087 1519.816 709.223 1618.643 1886.706
231 229 30e542e52a 2026-10-07 5776 Declare the namespace-scope constants in to_chars.hpp inline (#5776) 1934.934 3823.724 10229.636 2916.698 3929.565 829.102 452.279 543.038 6951.995 837.059 1524.049 720.722 1619.823 1903.938
232 230 367336c83d 2026-10-07 5779 Fix CI on develop after #5585 (#5779) 1928.921 3780.927 10153.395 2883.604 3877.750 824.488 451.999 543.662 6927.395 835.495 1506.387 694.058 1622.903 1907.732
233 231 069ace74af 2026-10-07 5707 Round-trip BJData ND-array annotations exactly (single precision, key order) (#5707) 1937.387 3843.716 10184.302 2923.323 3936.570 827.610 456.123 543.169 6907.756 847.020 1515.229 696.202 1626.001 1901.142
234 232 43fe8928e1 2026-10-07 5781 Stop binary writers overflowing the stack on deep values (#5781) 1961.046 3868.274 10300.573 2899.792 3982.526 845.594 461.395 543.298 7059.093 846.696 1522.728 697.717 1623.846 1921.370
235 233 a5f5d3059b 2026-10-07 5772 Make std::hash<basic_json> consistent with operator== for numbers (#5772) 1949.220 3857.159 10170.427 2890.052 3981.349 840.234 459.334 541.947 6953.786 843.495 1509.713 703.339 1627.086 1911.653
236 234 a269794db7 2026-10-08 5782 Use MSVC intrinsics for full multiplication (#5782) 1931.869 3817.742 10159.666 2902.820 3903.263 840.740 455.827 540.621 6884.562 843.272 1513.776 702.028 1614.459 1901.008
237 235 69a0c1b82c 2026-10-09 5328 Avoid allocating temporary basic_json for cbor and msgpack object keys (#5328) 1909.579 3777.560 10065.682 2852.732 3897.659 833.289 459.856 540.631 6882.354 833.998 1498.288 314.059 1609.343 1906.714
238 236 374dfe4f0f 2026-10-09 5791 Keep converted object keys alive while writing UBJSON and BJData (#5791) 1911.274 3827.188 10159.553 2886.568 3890.388 833.632 459.800 542.649 6954.547 838.507 1509.324 314.357 1613.655 1892.838
239 237 44e8597701 2026-10-09 5792 Flatten deeply nested values without recursing per nesting level (#5792) 1940.103 3811.779 10139.396 2865.050 3874.896 835.001 459.686 544.065 6866.943 836.862 1496.298 314.617 1614.837 1891.741
240 238 2913e96433 2026-10-09 5793 Unflatten in time and memory linear in the pointer depth (#5793) 1908.453 3785.099 10262.147 2878.961 3920.657 845.619 459.806 543.998 6874.813 832.659 1486.901 312.175 1589.620 1863.981
241 239 84ee12a67c 2026-10-09 5797 Make UTF8_ACCEPT/UTF8_REJECT inline variables to avoid TU-local exposure in modules (#5797) 1922.691 3792.849 10162.656 2871.562 3887.719 836.308 456.522 542.577 6912.807 840.369 1497.447 313.683 1609.988 1899.591
242 240 1649d9eda4 2026-10-11 5783 Use and extend the detail helpers to remove duplicated code (#5783) 1916.258 3804.242 10297.344 2913.118 3847.662 836.519 453.270 538.750 6953.015 832.774 1506.068 324.715 1596.974 1875.878
243 241 2cca04ae6f 2026-10-11 5800 Report one-character non-numeric array indices like longer ones (#5800) 1932.327 3803.750 10135.438 2881.041 3894.622 840.016 458.569 538.037 6842.948 829.444 1499.722 324.811 1607.194 1875.851
244 242 74a03dec84 2026-10-11 5802 Throw type_error.321 for discarded values in to_bon8 (#5802) 1924.695 3814.854 10084.239 2873.180 3848.498 839.406 450.575 534.181 6893.005 834.300 1503.369 324.389 1607.323 1887.871
245 243 e8b747e4bc 2026-10-11 5808 Re-amalgamate single_include after #5795 and #5806 (#5808) 1937.995 3840.622 10221.990 2896.024 3885.568 834.394 458.874 539.771 6906.182 839.793 1517.689 324.800 1609.838 1890.885
246 244 40a62947d3 2026-10-12 4965 support JSON Merge Patch (RFC 7396) diff creation (#4965) 1932.021 3822.188 10248.416 2924.560 3980.331 842.462 459.010 540.237 6978.526 838.941 1529.508 326.435 1636.153 1917.472
247 245 f23830b65e 2026-10-13 5809 Derive the lexer position lazily for seekable input (#5809) 1814.075 3368.028 9974.755 2807.532 3943.229 647.639 457.018 551.206 6954.166 843.355 1522.762 315.716 1618.953 1903.816
248 246 aa9620fb15 2026-10-13 5810 Skip the indentation after a newline 8 bytes at a time (#5810) 1719.629 2959.344 10139.771 2799.555 3939.292 592.867 465.821 545.858 6968.068 849.167 1519.774 315.385 1629.981 1907.253
249 247 e839bbd1c0 2026-10-13 5813 Export client-facing headers from json.hpp for IWYU / include-cleaner, and check clients in CI (#5813) 1725.742 2949.070 10136.603 2821.591 3919.927 589.957 463.642 544.851 6987.427 843.151 1517.562 314.425 1619.671 1903.613
250 248 5b4c8f9b00 2026-10-14 5738 Speed up the lexer: own float parser, string scan, and \u table (#5738) 1615.668 2934.565 8763.651 2794.503 3928.286 559.107 374.921 516.391 6937.140 815.776 1513.238 325.043 1625.226 1912.905
251 249 91a7a94cc6 2026-10-14 5634 Write doubles with the shortest digits (Żmij), digits in registers (#5634) 1613.126 2929.599 8708.599 2783.954 3874.248 548.449 363.632 468.127 2421.176 745.466 1511.406 323.743 1614.195 1900.392
252 250 a6e9785ab6 2026-10-15 5831 Look up the key only once in the callback parser's key() (#5831) 1589.309 2938.557 8798.823 2767.872 3882.154 547.301 364.257 467.833 2395.851 744.716 1506.830 316.192 1623.771 1899.458
253 251 0c4e7c103c 2026-10-15 5834 Make flatten() linear for ordered_json (#5834) 1625.754 2936.203 8755.088 2793.081 3879.740 557.529 366.745 468.359 2418.388 746.210 1524.325 315.954 1614.677 1898.544
254 252 0a4b3a84ee 2026-10-15 5836 Speed up JSON pointer parsing, formatting, comparison and lookup (#5836) 1622.914 2915.901 8819.073 2783.990 3922.758 558.429 366.216 470.019 2427.606 747.168 1526.881 316.972 1625.611 1912.601
255 253 6ba53e63dd 2026-10-15 5833 Speed up array-to-container from_json (#5833) 1626.155 2920.747 8777.989 2782.870 3988.206 560.154 367.695 469.892 2427.262 749.301 1529.474 316.399 1631.810 1915.217
256 254 ca7740fef2 2026-10-15 5837 Move elements when converting rvalue containers to JSON (#5837) 1615.747 2928.778 8765.792 2773.062 3926.456 561.034 367.498 469.807 2424.344 748.423 1523.215 316.339 1624.374 1894.455
257 255 4530d9681c 2026-10-15 5832 Fix quadratic parent updates for ordered_json with JSON_DIAGNOSTICS (#5832) 1618.937 2911.378 8794.094 2763.191 3886.974 555.789 366.475 469.275 2415.231 746.755 1512.590 315.856 1618.226 1899.284
258 256 91869983a0 2026-10-15 5840 Make the value lifecycle inline-friendly (#5840) 1595.075 2832.274 8420.390 2690.050 3876.841 555.209 366.118 469.783 2424.335 747.931 1485.914 314.048 1549.787 1775.823
259 257 6a27b9acb2 2026-10-15 5838 Construct remaining hot-path exceptions out of line so core functions inline (#5838) 1589.535 2824.360 8466.755 2699.690 3888.990 557.917 364.879 471.601 2422.995 746.543 1498.371 314.978 1539.656 1797.752
260 258 4f11512641 2026-10-15 5835 Speed up container destruction, iterator access and diff() (#5835) 1515.750 2714.756 8639.213 2574.698 3805.860 561.827 366.793 469.680 2421.769 748.727 1383.744 317.248 1446.525 1705.789
261 259 ed86019a21 2026-10-15 5839 Move binary reader error construction out of line (#5839) 1507.907 2766.774 8597.870 2622.289 3767.638 553.026 362.644 468.482 2408.731 744.936 1362.080 324.833 1445.531 1703.216
262 260 6261d1e432 2026-10-15 5842 Construct the JSON Patch exceptions out of line (#5842) 1532.015 2756.867 8670.677 2617.989 3869.133 558.865 365.834 469.932 2435.279 750.295 1380.628 327.010 1453.340 1705.232
263 261 ce28c722bc 2026-10-15 5815 Allow the same type for number_integer_t and number_unsigned_t (#5815) 1533.045 2775.807 8543.755 2615.412 3776.721 553.127 365.866 471.174 2433.384 745.309 1372.372 328.405 1452.848 1716.649
264 262 91b9ee2602 2026-10-15 5829 Update cppcheck to 1.5.2 (Cppcheck 2.20) and fix its new findings (#5829) 1516.450 2748.961 8571.521 2599.870 3807.744 557.303 367.220 472.209 2421.389 743.889 1379.405 326.087 1451.926 1710.506
265 263 dcb96e82fb 2026-10-15 5822 Escape characters below 0x60 from a table straight into the write buffer (#5822) 1525.777 2734.963 8524.771 2588.289 3790.726 557.907 360.057 463.574 2430.626 743.382 1375.816 325.308 1439.947 1695.307
266 264 b41228c227 2026-10-15 5843 Fix AppVeyor failures from the Zmij double writer (#5843) 1497.922 2690.614 8406.906 2582.482 3726.195 548.374 352.932 459.663 2398.953 737.639 1347.507 322.827 1429.640 1682.775
267 265 4da73dc5ff 2026-10-15 5858 Fix compiler warnings on develop from the API performance stack (#5858) 1523.138 2731.825 8474.073 2593.149 3782.769 553.758 359.180 462.915 2380.246 739.049 1346.755 324.909 1441.408 1698.043
268 266 5683f5e024 2026-10-15 5859 Define less_general() only without three-way comparison (#5859) 1504.689 2739.172 8603.693 2605.159 3797.057 560.213 358.865 464.429 2423.456 742.207 1374.000 326.702 1447.488 1712.379
269 267 cd6b428ef0 2026-10-16 5860 Fix CI failures on develop from the API performance stack (#5860) 1510.160 2732.695 8564.510 2603.242 3810.518 556.015 362.409 466.047 2437.364 745.153 1377.439 325.753 1444.892 1699.255
270 268 cc8334113c 2026-10-19 5866 Do not use Qt's keyword macros as identifiers (#5866) 1498.858 2732.644 8535.328 2587.258 3787.993 548.267 362.607 464.487 2403.147 735.633 1368.831 323.997 1442.709 1686.963
271 269 4da932f518 2026-10-19 5828 Make parsing from std::istream and FILE* fast (#5828) 1499.289 2723.605 8397.787 2597.237 1956.330 553.182 363.501 458.898 2397.342 733.054 1362.816 320.346 1429.314 1698.294
272 270 122d718330 2026-10-21 5620 Add json_document and json_view: node index, parser, and document (#5620) 1520.651 2751.099 8527.135 2588.494 1994.466 560.384 362.257 461.917 2393.611 741.198 1362.167 328.620 1441.211 1691.238 230.700 389.375 976.277
273 271 43e97b629b 2026-10-21 5622 Add element access, iteration, values, and JSON pointers to json_view (#5622) 1493.875 2687.307 8383.354 2567.078 1986.311 547.934 353.938 462.380 2400.331 737.098 1374.560 322.012 1445.504 1686.421 231.353 386.679 958.441
274 272 4c3a3eb5b5 2026-10-21 5624 Add dump() and comparisons to json_view (#5624) 1502.926 2714.747 8522.161 2608.565 2001.856 552.014 359.510 462.656 2393.110 732.091 1366.524 324.313 1442.119 1682.564 228.836 393.082 976.976
275 273 3ff37ead75 2026-10-21 5628 Scan json_view strings with SIMD and index large objects (#5628) 1514.580 2728.619 8406.562 2609.758 2041.176 556.017 357.330 462.573 2383.158 733.939 1368.057 324.391 1442.711 1700.884 177.833 367.806 950.071
276 274 823eee3b59 2026-10-21 5630 Add editable json_documents: set, push_back, insert, and erase (#5630) 1498.134 2754.810 8537.062 2588.474 1994.441 556.670 353.931 463.646 2392.987 740.023 1357.930 324.129 1441.622 1698.022 181.404 376.470 962.253
277 275 4971200b54 2026-10-21 5632 Add images of json_documents: save() and load() (#5632) 1494.231 2681.211 8425.834 2543.276 1984.849 548.146 354.762 460.440 2414.747 734.679 1363.841 321.349 1421.806 1670.134 177.777 368.631 949.292
278 276 4155e2938f 2026-10-21 5633 Write json_view's dump() without a call or conversion per token (#5633) 1500.247 2712.357 8612.193 2597.211 2012.860 558.559 359.889 462.371 2412.896 739.048 1372.456 324.070 1441.546 1697.571 180.320 371.514 954.088
279 277 08d7fbb0a1 2026-10-21 5874 Read FILE* input with std::fgetc under MemorySanitizer (#5874) 1543.124 2758.211 8565.730 2584.453 2046.255 558.522 358.865 464.542 2421.435 743.715 1374.005 324.687 1462.572 1700.819 180.714 372.601 965.361
280 278 0cbe95ffa2 2026-10-21 5824 Speed up writing CBOR and MessagePack, above all integer arrays (#5824) 1501.550 2706.534 8707.120 2584.807 2039.728 551.688 360.692 466.024 2397.182 742.777 1361.847 201.488 1429.223 1682.436 178.641 371.038 946.389
281 279 bd5227c2ec 2026-10-21 5805 Fix silent wrong results for custom number types (#5805) 1511.036 2733.325 8786.406 2588.906 2000.483 553.456 360.458 465.989 2398.381 743.338 1370.524 201.168 1444.051 1701.345 179.776 372.557 954.733
282 280 e13e976801 2026-10-21 5851 Accumulate number digits while scanning them (#5851) 1501.737 2667.570 7762.365 2523.289 1987.518 545.368 359.336 462.056 2407.652 739.226 1368.104 200.632 1440.390 1688.117 178.721 374.278 956.353
283 281 5e13f834c1 2026-10-21 5852 Copy the text of float tokens only when a SAX handler asks for it (#5852) 1512.318 2655.312 7314.354 2515.044 2019.288 547.993 362.038 463.788 2410.262 745.839 1364.898 208.969 1450.422 1713.902 179.198 371.996 968.699
284 282 e9970066c5 2026-10-21 5853 Scan strings with SSE2, SSSE3, or NEON (#5853) 1488.705 2654.404 7339.589 2551.050 2015.716 486.719 341.381 475.591 2434.369 756.973 1376.754 208.797 1449.981 1706.044 182.358 379.153 968.355
285 283 fa37b952df 2026-10-21 5854 Match literals without a stack array and keep parser states in bytes (#5854) 1471.894 2619.164 7285.000 2485.883 1949.380 471.534 347.785 475.287 2413.552 751.487 1374.254 207.522 1443.177 1699.611 181.643 377.971 977.268
286 284 52fecc1fab 2026-10-21 5855 Move object keys into the value when parsing (#5855) 1392.599 2628.688 7362.562 2485.293 1882.663 471.968 339.711 473.663 2414.903 751.376 1319.857 200.185 1448.057 1705.675 179.410 371.865 963.306
287 285 6aefd8c662 2026-10-21 5878 Copy short printable-ASCII strings without starting the scanner (#5878) 1399.384 2664.401 7232.557 2535.425 1922.431 470.185 320.230 418.440 2446.082 696.786 1317.889 201.955 1447.217 1701.135 180.860 376.217 968.215
288 286 7c26e99ac5 2026-10-21 5879 Copy ASCII strings in the view's dump with ensure_ascii (#5879) 1361.839 2610.182 7187.115 2471.708 1853.592 464.274 313.821 414.316 2388.840 687.851 1318.253 200.399 1434.986 1697.487 178.601 368.595 947.799
289 287 3e031b06a5 2026-10-21 5876 Use standard library helpers where available, with C++11 fallbacks (#5876) 1381.599 2592.122 7336.719 2499.994 1848.434 467.895 315.257 415.788 2430.769 692.250 1311.164 200.424 1444.303 1698.311 180.149 374.484 961.091
290 288 9bf531436f 2026-10-21 5861 Speed up flatten(), unflatten(), diff() and patch() (#5861) 1379.301 2613.219 7170.433 2472.628 1853.035 467.161 315.217 412.303 2406.597 683.062 1298.512 198.681 1434.089 1682.912 177.511 368.116 947.255
291 289 9855db81f3 2026-10-22 5881 Silence macro-to-enum for the endianness macros (#5881) 1369.150 2613.547 7209.787 2476.232 1841.347 467.780 316.011 416.187 2415.504 686.920 1304.263 200.868 1441.243 1694.603 178.739 368.123 948.579
292 290 aa0b371f7c 2026-10-23 5884 Faster std::istream input: inline get-area path, binary reads, unbuffered streambufs (#5884) 1375.030 2569.362 7218.375 2484.425 1743.476 470.240 319.245 403.750 2436.034 679.759 1319.508 201.531 1443.354 1698.057 180.133 372.206 946.488
293 291 86d5c56c54 2026-10-23 5886 Speed up flatten(), unflatten(), diff() and patch() further (#5886) 1386.169 2622.331 7281.551 2495.923 1700.794 472.317 317.282 403.416 2409.097 682.507 1320.319 200.963 1444.908 1697.678 179.138 375.751 954.573
294 292 dec0e9b749 2026-10-23 5883 Write strings, scalars and indentation in dump() with fewer calls (#5883) 1383.235 2621.847 7151.412 2491.644 1732.469 473.034 211.016 288.685 2276.953 416.068 1318.490 200.574 1452.099 1701.256 180.064 372.324 960.583
295 293 6fa14d8f95 2026-10-23 5885 Write binary formats through reserved sink space and number runs (#5885) 1366.956 2600.914 7176.994 2465.343 1691.333 462.351 210.662 285.259 2301.553 417.589 1324.173 136.601 1429.240 1687.947 179.319 368.881 962.518
296 294 0b924f5375 2026-10-23 5887 Split and print JSON pointers in one pass (#5887) 1377.526 2597.394 7242.688 2464.445 1739.841 466.382 211.716 288.202 2319.771 418.288 1318.592 138.744 1441.983 1706.639 179.684 372.087 976.078
297 295 e9c4fe3cdf 2026-10-24 5889 json_view: indented and ensure_ascii dumps through the fast writer (#5889) 1393.007 2627.226 7248.287 2491.551 1769.642 469.976 211.665 291.327 2305.655 420.168 1319.431 139.577 1457.965 1712.927 182.274 377.741 983.284
298 296 dd7686a269 2026-10-24 5888 json_view: faster reading, indexing and C-stream parsing (#5888) 1382.444 2607.026 7161.365 2472.635 1701.277 468.438 209.963 287.564 2276.329 415.511 1311.194 137.875 1439.700 1696.646 177.624 367.131 977.802
299 297 9c50bdd140 2026-10-24 5882 Make the DOM parser cheaper per container and per member (#5882) 1392.673 2461.082 6068.625 2334.706 1696.950 475.550 209.313 291.776 2300.287 416.349 1317.581 138.194 1441.209 1707.720 178.751 367.339 978.031
300 298 01139dc192 2026-10-24 5905 Silence an Infer false positive in json_view materialize (#5905) 1381.470 2463.013 6078.010 2335.216 1709.088 475.718 211.023 291.212 2275.302 418.098 1320.441 137.572 1443.434 1696.436 175.969 365.658 975.272
301 299 fe5e401870 2026-10-25 5901 Consolidate duplicated detail helpers and bodies (#5891) (#5901) 1395.881 2462.765 6066.698 2327.708 1706.745 474.184 212.683 289.321 2283.842 417.657 1314.153 138.084 1442.796 1696.588 177.144 364.092 961.847
302 300 3eae5680d6 2026-10-25 5902 from_json: number-first dispatch for arithmetic types, loop for std::array (#5902) 1397.343 2477.060 6080.864 2340.781 1711.774 481.523 213.618 289.360 2289.503 417.517 1313.541 138.271 1440.822 1695.785 178.731 367.293 983.555
303 301 2a56afc714 2026-10-25 5916 Fix VS 2015 build of the DOM parser (#5882) (#5916) 1373.929 2476.139 6056.797 2341.890 1749.167 482.883 215.107 290.053 2292.495 417.441 1320.640 137.868 1445.227 1702.064 177.912 367.669 984.794
304 302 d6431a9104 2026-10-26 5918 Throw out_of_range.411 for JSON Patch add into a null parent (#5917) (#5918) 1371.635 2445.905 6017.636 2314.178 1696.447 478.134 210.996 287.397 2278.718 414.186 1291.197 137.374 1436.212 1682.197 175.790 361.130 962.070
305 303 81d66291c5 2026-10-26 5358 Create objects for pointer tokens that cannot be array indices (#5358) 1382.909 2465.649 6052.114 2332.556 1711.721 479.927 213.359 289.913 2289.412 417.201 1311.695 137.572 1437.168 1696.302 177.495 367.526 963.924
306 304 d5da84249f 2026-10-26 5927 Skip CBOR tags in front of map keys, validate indefinite text chunks, fix CBOR docs (#5927) 1374.553 2476.464 6076.834 2346.075 1744.224 483.375 211.423 291.148 2287.800 420.247 1320.015 137.369 1449.068 1704.785 177.459 365.004 963.908
307 305 0c3570d44a 2026-10-26 5929 Validate the UBJSON/BJData container type marker for count 0; fix UBJSON docs (#5929) 1381.462 2462.578 6055.183 2329.970 1713.086 484.962 210.683 290.024 2260.371 416.895 1319.093 137.782 1453.495 1706.801 177.031 361.025 962.952
308 306 dc768a7d5d 2026-10-26 5930 Fix BSON binary subtype 0x02 and check the declared document size earlier (#5930) 1386.856 2463.400 6054.255 2337.105 1746.441 485.425 214.508 290.954 2314.702 418.769 1325.164 139.255 1452.125 1718.313 179.005 367.327 977.054
309 307 60107eda3f 2026-10-26 5931 Read BJData ND-arrays of float16, restrict ND-array char to 0..127, correct BJData docs (#5931) 1389.051 2464.457 6049.084 2336.727 1710.473 483.159 213.007 288.990 2285.073 417.663 1317.537 137.893 1443.301 1697.126 178.706 364.051 962.202
310 308 731f1b5bfb 2026-10-26 5919 json_view: view_mode enum instead of bool Editable, node_kind for node::kind (#5919) 1381.664 2428.529 5978.713 2333.485 1746.571 479.163 211.036 288.957 2281.592 416.990 1308.904 137.486 1447.665 1691.427 175.453 363.704 963.371
311 309 4cdfa6d0f4 2026-10-26 5920 json_view: no save() and load() on big-endian targets (#5920) 1390.901 2477.841 6102.474 2337.925 1777.003 485.382 214.373 290.946 2303.147 421.178 1321.976 139.942 1446.726 1704.816 179.928 367.825 976.532
312 310 5a2819c940 2026-10-26 5921 json_view: one SIMD macro set with the library (#5921) 1393.409 2479.841 6073.011 2350.336 1785.087 485.658 214.651 292.044 2304.448 418.026 1326.212 138.942 1468.981 1719.505 179.174 368.704 982.764
313 311 e5fe4ebdd2 2026-10-26 5922 json_view: from_json() of the macros reads views directly (#5922) 1384.612 2467.078 6056.328 2337.309 1742.751 482.554 213.389 289.543 2299.118 417.521 1309.673 138.237 1448.628 1704.550 177.925 365.163 984.351
314 312 9e67bfa115 2026-10-26 5923 json_view: the library's std conversions read views directly (#5923) 1395.103 2482.517 6066.604 2350.538 1751.603 482.504 213.399 290.185 2306.188 420.406 1317.415 138.730 1444.367 1708.720 178.016 369.111 975.875
315 313 21ec9bd801 2026-10-27 5915 json_view: fewer allocations when parsing small documents (#5915) 1388.282 2469.118 6066.495 2340.391 1744.901 478.745 214.934 292.970 2309.264 422.842 1323.237 138.541 1454.151 1707.314 178.058 366.514 958.110
316 314 2bb2feeef4 2026-10-27 5942 Fix the red CI on develop (json_view pointer tokens, bson, from_json tests, Infer, IWYU) (#5942) 1391.981 2468.266 6068.495 2335.707 1751.527 482.908 214.285 291.291 2300.453 417.876 1328.089 138.010 1454.934 1701.845 178.250 367.182 964.917
317 315 78a0687147 2026-10-27 5940 Strong exception guarantee for operator[](json_pointer) (#5940) 1379.414 2467.492 6109.136 2335.309 1723.090 480.260 216.197 292.075 2313.798 415.444 1314.530 138.314 1449.629 1698.792 177.628 364.844 965.314
318 316 candidate develop + open pull requests 1383.171 2465.866 6049.771 2336.394 1725.095 480.882 214.967 292.621 2289.324 418.010 1320.853 137.793 1439.615 1710.333 176.356 364.229 962.166
+360
View File
@@ -0,0 +1,360 @@
"""Draws the figures of home/blog/how_3_13_0_got_faster.md as inline SVGs into docs/images/.
Generated files:
- perf_blog_overview.svg: speedup of 3.13.0 over 3.12.0 per workload (Google Benchmark suite)
- perf_blog_timeline_<workload>.svg: speedup over 3.12.0 of eight workloads at every develop commit that changed
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
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.
Like the figures of charts.py, the SVGs are not images: the page includes their text with
`--8<-- "images/<name>.svg"`, so they follow the colours and fonts of the page (`nj-charts` rules in
docs/css/fig-charts.css, `nj-fig` rules in docs/css/brand.css). Run `python3 scripts/figures/perf_blog.py` from
docs/mkdocs after changing data or drawing, and commit the generated files.
"""
import csv
import html
import math
import re
from pathlib import Path
HERE = Path(__file__).resolve().parent
OUT = HERE.parents[1] / "docs" / "images"
MINUS = "&#8722;"
TIMES = "&#215;"
# words the abbreviation extension (includes/glossary.md) would wrap in <abbr> inside the SVG text
ABBR = re.compile(r"(?<![\w;])(BJData|BON8|BSON|CBOR|GCC|UBJSON|MsgPack|JSON|DOM|SAX|SIMD|UTF|ASCII)(?!\w)")
def protect(text):
return ABBR.sub(lambda m: m.group(1)[0] + "&#8203;" + m.group(1)[1:], text)
def esc(s):
return html.escape(s, quote=True).replace("&amp;#", "&#")
def write(name, W, H, cls, tid, title, desc, body):
s = ['<svg class="nj-fig nj-charts %s" viewBox="0 0 %g %g" role="img" aria-labelledby="%s %s-d" '
'xmlns="http://www.w3.org/2000/svg">' % (cls, W, H, tid, tid),
'<title id="%s">%s</title>' % (tid, esc(title)),
'<desc id="%s-d">%s</desc>' % (tid, esc(desc))]
s += body
s.append('</svg>')
text = protect("\n".join(s)) + "\n"
assert "\n\n" not in text # a blank line would end the raw HTML block
(OUT / name).write_text(text)
def hbar(x0, x1, y, h, r=4):
"""Horizontal bar from the baseline x0 to x1, rounded only at the data end."""
if abs(x1 - x0) < 0.5:
return "M%g %g h0.5 v%g h-0.5 Z" % (x0, y, h)
r = min(r, h / 2, abs(x1 - x0))
s = 1 if x1 > x0 else -1
return ("M%g %g H%g Q%g %g %g %g V%g Q%g %g %g %g H%g Z"
% (x0, y, x1 - s * r, x1, y, x1, y + r, y + h - r, x1, y + h, x1 - s * r, y + h, x0))
def fx(v):
"""speedup factor for labels: 2 significant digits below 10, integers above"""
if v >= 100:
return "%d%s" % (round(v), TIMES)
if v >= 10:
return "%.0f%s" % (v, TIMES)
return "%.1f%s" % (v, TIMES) if v >= 1.995 else "%.2f%s" % (v, TIMES)
# ---------- SWAR: one word of a string ----------
def swar():
text = 'witter",'
W, H = 640, 312
L, cw, top = 40, 70, 34
b = []
b.append('<text class="fg-h" x="%g" y="20">eight input bytes, loaded as one 64-bit word (byte 0 is the lowest)</text>' % L)
for i, ch in enumerate(text):
x = L + i * cw
special = ch == '"'
b.append('<rect class="fg-cell" x="%g" y="%g" width="%g" height="40" rx="4"/>' % (x, top, cw - 6))
if special:
b.append('<rect class="nj-charts-c2" fill-opacity=".25" x="%g" y="%g" width="%g" height="40" rx="4"/>' % (x, top, cw - 6))
b.append('<text class="fg-code" x="%g" y="%g" text-anchor="middle">%s</text>' % (x + (cw - 6) / 2, top + 26, esc(ch)))
b.append('<text class="nj-charts-tick" x="%g" y="%g">0x%02X</text>' % (x + (cw - 6) / 2, top + 58, ord(ch)))
b.append('<text class="nj-charts-tick" x="%g" y="%g">byte %d</text>' % (x + (cw - 6) / 2, top + 74, i))
# result row
y2 = top + 112
b.append('<text class="fg-h" x="%g" y="%g">swar_string_special(): the high bit of each byte that needs handling</text>' % (L, y2 - 14))
for i, ch in enumerate(text):
x = L + i * cw
special = ch == '"'
b.append('<rect class="fg-cell" x="%g" y="%g" width="%g" height="34" rx="4"/>' % (x, y2, cw - 6))
if special:
b.append('<rect class="nj-charts-c2" fill-opacity=".25" x="%g" y="%g" width="%g" height="34" rx="4"/>' % (x, y2, cw - 6))
b.append('<text class="fg-code" x="%g" y="%g" text-anchor="middle">%s</text>'
% (x + (cw - 6) / 2, y2 + 23, "0x80" if special else "0x00"))
# conclusion
y3 = y2 + 70
b.append('<text class="fg-code" x="%g" y="%g">count_trailing_zeros(0x0080000000000000) = 55</text>' % (L, y3))
b.append('<text class="fg-code" x="%g" y="%g">55 / 8 = 6: copy bytes 0 to 5 in one go, then handle the quote</text>' % (L, y3 + 26))
b.append('<text class="fg-note fg-note--l" x="%g" y="%g">No branch per byte: a few subtractions, ANDs and ORs per word,</text>' % (L, y3 + 56))
b.append('<text class="fg-note fg-note--l" x="%g" y="%g">then one count of trailing zeros.</text>' % (L, y3 + 74))
write("perf_blog_swar.svg", W, H, "nj-charts--swar", "nj-blog-swar",
"Finding the end of a run of ordinary string characters eight bytes at a time",
"The eight bytes w, i, t, t, e, r, quote and comma are loaded as one word. The test sets the high bit only in "
"byte 6, the quote. Counting trailing zero bits gives 55, divided by eight gives 6: bytes 0 to 5 are copied "
"at once, then the quote ends the string.", b)
# ---------- overview: speedup per workload (Google Benchmark rows, 3.12.0 time / 3.13.0 time) ----------
# (group, label, speedup), copied from the table "The short version"
OVERVIEW = [
("Parsing", "twitter.json", 3.02),
("Parsing", "citm_catalog.json", 4.13),
("Parsing", "canada.json", 3.46),
("Parsing", "canada.json, indented", 6.74),
("Parsing", "citm, ordered_json", 6.58),
("Parsing", "twitter, std::ifstream", 2.46),
("Parsing", "citm, FILE*", 4.76),
("Parsing", "citm, accept()", 6.99),
("Writing", "dump() twitter", 6.67),
("Writing", "dump() canada", 2.95),
("Writing", "dump(4) citm", 4.63),
("Writing", "to_cbor() twitter", 4.50),
("Reading CBOR", "twitter, memory", 3.11),
("Reading CBOR", "twitter, FILE*", 6.31),
("Values", "diff() canada", 10.44),
("Values", "iterate canada", 2.69),
("Values", "copy + destroy citm", 1.11),
("Values", "== citm", 1.04),
]
def overview():
W, L, R = 560, 190, 520
hi = max(v for _, _, v in OVERVIEW)
hi = math.ceil(hi + 0.5)
X = lambda v: L + v / hi * (R - L)
pitch, bh, top = 24, 15, 34
b, desc = [], []
y = top
group = None
rows = []
for g, label, v in OVERVIEW:
if g != group:
if group is not None:
y += 10
b.append('<text class="nj-charts-panel" x="%g" y="%g">%s</text>' % (8, y + 12, esc(g)))
y += 22
group = g
rows.append((label, v, y))
y += pitch
axis_y = y + 2
for t in range(1, hi + 1):
b.append('<line class="nj-charts-grid" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(t), top, X(t), axis_y))
b.append('<text class="nj-charts-tick" x="%g" y="%g">%d%s</text>' % (X(t), axis_y + 16, t, TIMES))
for label, v, yy in rows:
b.append('<text class="nj-charts-rowlabel nj-charts-tick--r" x="%g" y="%g" text-anchor="end">%s</text>' % (L - 8, yy + bh - 3, esc(label)))
b.append('<path class="nj-charts-c1" d="%s"><title>%s: %s</title></path>' % (hbar(X(0), X(v), yy, bh), esc(label), fx(v)))
b.append('<text class="nj-charts-val" x="%g" y="%g">%s</text>' % (X(v) + 5, yy + bh - 3, fx(v)))
desc.append("%s %s" % (label, fx(v).replace(TIMES, "x")))
b.append('<line class="nj-charts-ref" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(1), top, X(1), axis_y))
b.append('<line class="nj-charts-zero" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(0), top, X(0), axis_y))
b.append('<text class="nj-charts-note" x="%g" y="%g">speedup over 3.12.0 (the line at 1%s is 3.12.0)</text>' % (L, 18, TIMES))
write("perf_blog_overview.svg", W, axis_y + 28, "nj-charts--blog", "nj-blog-overview",
"Speedup of 3.13.0 over 3.12.0 per workload, Apple M1 Max, Apple clang",
"Horizontal bars, longer is faster. " + "; ".join(desc) + ".", b)
# ---------- timeline: one panel per workload ----------
# (column in perf_timeline.csv, panel title, [PR numbers to label])
TIMELINE = [
("parse_citm", "parse() citm_catalog.json", [5234, 5283, 5592, 5809, 5810, 5882]),
("parse_canada", "parse() canada.json", [5234, 5283, 5617, 5738, 5851, 5882]),
("accept_twitter", "accept() twitter.json", [5234, 5283, 5592, 5809, 5810, 5853]),
("parse_twitter_ifstream", "parse() twitter.json, std::ifstream", [5828, 5884]),
("dump_twitter", "dump() twitter.json", [5285, 5738, 5878, 5883]),
("dump_canada", "dump() canada.json", [5285, 5634]),
("from_cbor_twitter", "from_cbor() twitter", [5233, 5501, 5185, 5746]),
("to_cbor_twitter", "to_cbor() twitter", [5328, 5824, 5885]),
]
MONTHS = [("2025-04", "3.12.0"), ("2026-09", "Sep 2026"), ("2026-10", "Oct")]
def timeline():
rows = list(csv.DictReader((HERE / "data" / "perf_timeline.csv").open()))
n = len(rows)
W, H = 340, 252
L, R, T, B = 44, 330, 62, 208
for col, title, labels in TIMELINE:
vals = [float(r[col]) if r[col] else None for r in rows]
base = vals[0]
rel = [base / v if v else None for v in vals] # speedup over 3.12.0
hi = max(x for x in rel if x)
top = 2 ** math.ceil(math.log2(hi * 1.3))
Y = lambda s: B - math.log2(s) / math.log2(top) * (B - T)
X = lambda i: L + i / (n - 1) * (R - L)
b = ['<text class="nj-charts-panel" x="%g" y="18">%s</text>' % (8, esc(title))]
t = 1
while t <= top:
b.append('<line class="nj-charts-grid" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (L, Y(t), R, Y(t)))
b.append('<text class="nj-charts-tick nj-charts-tick--r" x="%g" y="%g">%d%s</text>' % (L - 6, Y(t) + 4, t, TIMES))
t *= 2
# month ticks: first commit of the month
seen = set()
for i, r in enumerate(rows):
m = r["date"][:7]
for key, name in MONTHS:
if m == key and key not in seen:
seen.add(key)
b.append('<line class="nj-charts-axis" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(i), B, X(i), B + 4))
b.append('<text class="nj-charts-tick" x="%g" y="%g">%s</text>' % (X(i), B + 17, name))
# a step line: each commit's value holds until the next commit
pts, prev = [], None
for i, s in enumerate(rel):
if s is None:
continue
if prev is not None:
pts.append("%.1f,%.1f" % (X(i), Y(prev)))
pts.append("%.1f,%.1f" % (X(i), Y(s)))
prev = s
b.append('<polyline class="nj-charts-json" points="%s"/>' % " ".join(pts))
# labels for named steps: a dot at the commit and its PR number above it; PRs a few commits apart share a
# label, and a label that would overlap one already placed moves up
groups = []
for pr in labels:
i = next(k for k, r in enumerate(rows) if r["pr"] == str(pr))
if groups and X(i) - X(groups[-1][-1][1]) < 6:
groups[-1].append((pr, i))
else:
groups.append([(pr, i)])
# labels in two rows above the plot, each with a guide down to its dot
placed = []
for g in groups:
i = g[-1][1]
x, y = X(i), Y(rel[i])
for pr, k in g:
b.append('<circle class="nj-charts-json-dot" cx="%.1f" cy="%.1f" r="3.5"><title>#%s: %s</title></circle>'
% (X(k), Y(rel[k]), pr, fx(rel[k])))
text = ", ".join("#%s" % pr for pr, _ in g)
w = 7.2 * len(text)
tx = min(max(x, L + w / 2), R - w / 2)
row = 0
while any(r == row and abs(tx - px) < (w + pw) / 2 + 4 for px, r, pw in placed):
row += 1
placed.append((tx, row, w))
ty = 50 - 13 * row
b.append('<line class="nj-charts-grid" stroke-dasharray="2 2" x1="%.1f" y1="%.1f" x2="%.1f" y2="%.1f"/>' % (x, ty + 4, x, y - 5))
b.append('<text class="nj-charts-note" x="%.1f" y="%.1f" text-anchor="middle">%s</text>' % (tx, ty, text))
b.append('<line class="nj-charts-axis" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (L, B, R, B))
final = rel[-1]
desc = ("%s: speedup over 3.12.0 at each of %d commits, ending at %s. Labeled steps: %s."
% (title, n, fx(final).replace(TIMES, "x"), ", ".join("#%s" % p for p in labels)))
write("perf_blog_timeline_%s.svg" % col, W, H, "nj-charts--timeline", "nj-blog-tl-" + col,
"%s: speedup over 3.12.0 by commit" % title, desc, b)
# ---------- cliffs: 3.12.0 and 3.13.0 times on a log axis ----------
# (operation, 3.12.0 ms, 3.13.0 ms), copied from the table in "Fix the algorithm first"
CLIFFS = [
("diff() 64k numbers vs []", 4102, 9.98),
("diff() 20k objects vs half", 119, 3.85),
("parse() callback, 32k objects", 1334, 11.5),
("< nested 24 deep", 62.6, 0.002),
("< citm, 10x", 274, 3.81),
("flatten() citm, ordered_json", 253, 1.37),
("to_bson() 200 deep, 100x", 19.5, 0.566),
("push_back() 100k, diagnostics", 1514, 4.98),
("at(i) 10k, diagnostics", 43.2, 0.081),
]
def cliffs():
W, L, R = 600, 250, 585
lo, hi = -3, 4 # 1 µs .. 10 s, in log10 ms
X = lambda ms: L + (math.log10(ms) - lo) / (hi - lo) * (R - L)
top, pitch = 40, 34
b, desc = [], []
axis_y = top + pitch * len(CLIFFS) - 10
for e in range(lo, hi + 1):
b.append('<line class="nj-charts-grid" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(10 ** e), top - 10, X(10 ** e), axis_y))
lab = {-3: "1 µs", -2: "10 µs", -1: "0.1 ms", 0: "1 ms", 1: "10 ms", 2: "0.1 s", 3: "1 s", 4: "10 s"}[e]
b.append('<text class="nj-charts-tick" x="%g" y="%g">%s</text>' % (X(10 ** e), axis_y + 16, lab))
b.append('<circle class="nj-charts-ojson-dot" cx="%g" cy="14" r="5"/><text class="nj-charts-leg" x="%g" y="18.5">3.12.0</text>' % (L, L + 10))
b.append('<circle class="nj-charts-json-dot" cx="%g" cy="14" r="5"/><text class="nj-charts-leg" x="%g" y="18.5">3.13.0</text>' % (L + 80, L + 90))
for i, (op, old, new) in enumerate(CLIFFS):
y = top + i * pitch + 8
b.append('<text class="nj-charts-rowlabel" x="%g" y="%g" text-anchor="end">%s</text>' % (L - 10, y + 4, esc(op)))
b.append('<line class="nj-charts-axis" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(new), y, X(old), y))
b.append('<circle class="nj-charts-ojson-dot" cx="%g" cy="%g" r="5"><title>%s, 3.12.0: %g ms</title></circle>' % (X(old), y, esc(op), old))
b.append('<circle class="nj-charts-json-dot" cx="%g" cy="%g" r="5"><title>%s, 3.13.0: %g ms</title></circle>' % (X(new), y, esc(op), new))
b.append('<text class="nj-charts-factor" x="%g" y="%g">%s</text>' % ((X(old) + X(new)) / 2, y - 7, fx(old / new)))
desc.append("%s: %g ms to %g ms" % (op, old, new))
write("perf_blog_cliffs.svg", W, axis_y + 28, "nj-charts--blog", "nj-blog-cliffs",
"Operations that grew quadratically or worse: time with 3.12.0 and 3.13.0, log scale",
"Dot plot on a logarithmic time axis. " + "; ".join(desc) + ".", b)
# ---------- json_view: parse throughput ----------
# 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 = [(e, c, [n / (t * 1000) for n, t in zip(VIEW_BYTES, us)]) for e, c, us in VIEW_US] # GB/s
def view():
W, L, R = 580, 142, 545
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
group_h = len(VIEW) * (bh + gap) + 14
b, desc = [], []
x = 8
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
axis_y = top + group_h * len(VIEW_FILES)
t = 0.5
while t <= hi + 1e-9:
b.append('<line class="nj-charts-grid" x1="%g" y1="%g" x2="%g" y2="%g"/>' % (X(t), top - 4, X(t), axis_y))
b.append('<text class="nj-charts-tick" x="%g" y="%g">%g</text>' % (X(t), axis_y + 16, t))
t += 0.5
b.append('<text class="nj-charts-tick" x="%g" y="%g">GB/s, longer is faster</text>' % ((L + R) / 2, axis_y + 34))
for i, f in enumerate(VIEW_FILES):
y0 = top + i * group_h
b.append('<text class="nj-charts-rowlabel" x="%g" y="%g" text-anchor="end">%s</text>' % (L - 8, y0 + group_h / 2, esc(f)))
for j, (eng, cls, vals) in enumerate(VIEW):
y = y0 + j * (bh + gap)
b.append('<path class="%s" d="%s"><title>%s, %s: %.2f GB/s</title></path>' % (cls, hbar(X(0), X(vals[i]), y, bh), esc(eng), esc(f), vals[i]))
b.append('<text class="nj-charts-val" x="%g" y="%g">%.2f</text>' % (X(vals[i]) + 4, y + bh - 1.5, vals[i]))
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",
"Grouped horizontal bars in GB/s. " + "; ".join(desc) + ".", b)
if __name__ == "__main__":
swar()
if OVERVIEW:
overview()
if TIMELINE:
timeline()
if CLIFFS:
cliffs()
if VIEW:
view()
+3
View File
@@ -138,6 +138,9 @@ the `View*` benchmarks (in `src/benchmarks_view.cpp`) are only built if the dire
Only benchmarks present in both result files are compared, so for older releases, either filter the benchmarks or Only benchmarks present in both result files are compared, so for older releases, either filter the benchmarks or
build that release's own `tests/benchmarks` against its own header. build that release's own `tests/benchmarks` against its own header.
To find out *which commit* changed a number, [`history/`](history/README.md) times one fixed program against the
header of every commit that changed it.
## Getting stable numbers ## Getting stable numbers
- Build and run both versions on the same machine with the same compiler and Google Benchmark, one right after the - Build and run both versions on the same machine with the same compiler and Google Benchmark, one right after the
+43
View File
@@ -0,0 +1,43 @@
# Performance history
The benchmarks in [`tests/benchmarks`](../README.md) compare two versions. The program here answers a different
question: *which commit* made something faster or slower. `history.cpp` is one fixed benchmark that uses only API
3.12.0 already has. `history.py` compiles it against the `single_include` of every first-parent commit that changed
`json.hpp` or `json_view.hpp`, runs all of them interleaved, and writes one CSV row per commit with its pull request.
The timeline in the post [How 3.13.0 got faster](https://json.nlohmann.me/home/blog/how_3_13_0_got_faster/) comes from
it. It is not built by CMake or run by CI.
## Workloads
| name | what it does |
|---|---|
| `parse_twitter`, `parse_citm`, `parse_canada` | `json::parse()` of a `std::string` (`citm_catalog.json` as distributed is indented by four spaces) |
| `parse_citm_compact` | the same with a minified copy of `citm_catalog.json` |
| `parse_twitter_ifstream` | `json::parse()` of an `std::ifstream`, opening the file included |
| `accept_twitter` | `json::accept()` |
| `view_parse_*` | `json_document::parse()`; only where the header has `json_view.hpp` |
| `dump_twitter`, `dump_citm`, `dump_canada`, `dump4_citm` | `dump()` and `dump(4)` |
| `from_cbor_twitter`, `to_cbor_twitter` | read and write CBOR |
| `copy_destroy_citm` | copy a parsed document and destroy the copy |
| `equal_citm` | copy a parsed document and compare it with `==` |
Each workload runs in batches of at least 20 ms; the program prints the median of 9 batches in microseconds per call.
## Running it
```sh
mkdir -p ~/history/data
cp <json_test_data>/nativejson-benchmark/{twitter,citm_catalog,canada}.json ~/history/data/
python3 history.py build --repo ../../.. --work ~/history # about 300 builds, a few minutes in parallel
caffeinate -i python3 history.py run --work ~/history --rounds 4 # about 1 h 45 min on an M1 Max (about 4 s per binary and round)
python3 history.py summarize --work ~/history > history.csv
```
`--extra DIR` adds one more header directory, such as an amalgamation of `develop` with open pull requests merged
in. `run` waits whenever the 1-minute load average is 4 or more.
## Reading the results
A single commit can move a workload by a few percent through code layout alone: the functions it did not touch
move to other addresses. Read a change as a step only if it is larger than that and stays. To check one, time the
two commits against each other with more rounds, or compare instruction counts.
+88
View File
@@ -0,0 +1,88 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// One fixed benchmark, compiled against the json.hpp of every commit that changed it (see README.md).
// It uses only API that 3.12.0 has; the json_document rows exist only where the header has json_view.hpp.
// Usage: history <dir with twitter.json, citm_catalog.json, canada.json and citm_compact.json>
// Prints one line per workload: the name and the median of 9 batches in microseconds per call.
#include <nlohmann/json.hpp>
#if __has_include(<nlohmann/json_view.hpp>) && !defined(HISTORY_NO_VIEW)
#include <nlohmann/json_view.hpp>
#define HISTORY_VIEW 1
#endif
#include <algorithm>
#include <chrono>
#include <cstdio>
#include <fstream>
#include <functional>
#include <sstream>
#include <string>
#include <vector>
using nlohmann::json;
static std::string slurp(const std::string& p)
{
std::ifstream f(p, std::ios::binary);
std::stringstream s;
s << f.rdbuf();
return s.str();
}
static volatile std::size_t sink;
static void bench(const char* name, const std::function<std::size_t()>& f)
{
using clk = std::chrono::steady_clock;
sink = f(); // warm up
std::size_t n = 1;
for (;;)
{
auto t0 = clk::now();
for (std::size_t i = 0; i < n; ++i) sink = f();
double dt = std::chrono::duration<double>(clk::now() - t0).count();
if (dt > 0.02) break;
n *= 2;
}
std::vector<double> v;
for (int b = 0; b < 9; ++b)
{
auto t0 = clk::now();
for (std::size_t i = 0; i < n; ++i) sink = f();
v.push_back(std::chrono::duration<double, std::micro>(clk::now() - t0).count() / n);
}
std::sort(v.begin(), v.end());
std::printf("%s %.3f\n", name, v[4]);
}
int main(int, char** argv)
{
std::string d = argv[1];
const std::string tw = slurp(d + "/twitter.json"), ci = slurp(d + "/citm_catalog.json"),
ca = slurp(d + "/canada.json"), cii = slurp(d + "/citm_compact.json");
const json jtw = json::parse(tw), jci = json::parse(ci), jca = json::parse(ca);
const std::vector<std::uint8_t> cbtw = json::to_cbor(jtw);
bench("parse_twitter", [&] { return json::parse(tw).size(); });
bench("parse_citm", [&] { return json::parse(ci).size(); });
bench("parse_canada", [&] { return json::parse(ca).size(); });
bench("parse_citm_compact", [&] { return json::parse(cii).size(); });
bench("parse_twitter_ifstream", [&] { std::ifstream f(d + "/twitter.json"); return json::parse(f).size(); });
bench("accept_twitter", [&] { return static_cast<std::size_t>(json::accept(tw)); });
#ifdef HISTORY_VIEW
bench("view_parse_twitter", [&] { const auto doc = nlohmann::json_document::parse(tw); return doc.root().size(); });
bench("view_parse_citm", [&] { const auto doc = nlohmann::json_document::parse(ci); return doc.root().size(); });
bench("view_parse_canada", [&] { const auto doc = nlohmann::json_document::parse(ca); return doc.root().size(); });
#endif
bench("dump_twitter", [&] { return jtw.dump().size(); });
bench("dump_citm", [&] { return jci.dump().size(); });
bench("dump_canada", [&] { return jca.dump().size(); });
bench("dump4_citm", [&] { return jci.dump(4).size(); });
bench("from_cbor_twitter", [&] { return json::from_cbor(cbtw).size(); });
bench("to_cbor_twitter", [&] { return json::to_cbor(jtw).size(); });
bench("copy_destroy_citm", [&] { json c = jci; return c.size(); });
bench("equal_citm", [&] { json c = jci; return static_cast<std::size_t>(c == jci); });
}
+151
View File
@@ -0,0 +1,151 @@
#!/usr/bin/env python3
# __ _____ _____ _____
# __| | __| | | | JSON for Modern C++ (supporting code)
# | | |__ | | | | | | version 3.12.0
# |_____|_____|_____|_|___| https://github.com/nlohmann/json
#
# SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
# SPDX-License-Identifier: MIT
"""Time one fixed benchmark against the json.hpp of every commit that changed it.
Usage:
history.py build --repo REPO --work DIR [--from v3.12.0] [--to origin/develop] [--extra INCLUDE_DIR]
history.py run --work DIR [--rounds 4]
history.py summarize --work DIR [--repo REPO] > history.csv
build: lists the first-parent commits between --from and --to that changed single_include/nlohmann/json.hpp or
json_view.hpp, extracts single_include/ of each (and of --from itself), and compiles history.cpp against it into
DIR/bin/NNN, NNN being the line of the commit in DIR/commits.txt. --extra adds one more header directory at the end,
for example an amalgamation of develop with open pull requests merged in. It also writes the input files to DIR/data
(the nativejson-benchmark files from the test data, which must be in DIR/data already, plus a minified copy of
citm_catalog.json).
run: runs every binary once per round, in a new random order each round, and only while the 1-minute load average is
below 4. Output: DIR/res/NNN-R.txt.
summarize: the median over the rounds per binary and workload, as CSV with the commit, its date and its pull request.
Only the Python 3 standard library is used; a C++17 compiler (c++) and git are needed.
"""
import argparse
import concurrent.futures
import csv
import json
import os
import random
import re
import statistics
import subprocess
import sys
import time
from pathlib import Path
HERE = Path(__file__).resolve().parent
FLAGS = ["-std=c++17", "-O3", "-DNDEBUG", "-w"]
def git(repo, *args):
return subprocess.run(["git", "-C", str(repo), *args], check=True, capture_output=True, text=True).stdout
def build_one(work, idx, rev, repo):
hdr = work / "hdr" / idx
hdr.mkdir(parents=True, exist_ok=True)
if rev.startswith("dir:"):
subprocess.run(["cp", "-R", rev[4:] + "/nlohmann", str(hdr)], check=True)
else:
archive = subprocess.run(["git", "-C", str(repo), "archive", rev, "single_include/nlohmann"],
check=True, capture_output=True).stdout
subprocess.run(["tar", "-x", "-C", str(hdr), "--strip-components=1"], input=archive, check=True)
out = work / "bin" / idx
cmd = ["c++", *FLAGS, "-I", str(hdr), str(HERE / "history.cpp"), "-o", str(out)]
# json_view.hpp of the first commits that had it may not compile with history.cpp: time json.hpp alone then
if subprocess.run(cmd, capture_output=True).returncode != 0:
if subprocess.run(cmd[:-4] + ["-DHISTORY_NO_VIEW"] + cmd[-4:], capture_output=True).returncode != 0:
return "FAIL %s %s" % (idx, rev)
return None
def build(a):
work, repo = Path(a.work), Path(a.repo)
(work / "bin").mkdir(parents=True, exist_ok=True)
revs = [a.__dict__["from"]] + git(repo, "log", "--first-parent", "--reverse", "--format=%H",
"%s..%s" % (a.__dict__["from"], a.to), "--",
"single_include/nlohmann/json.hpp", "single_include/nlohmann/json_view.hpp").split()
if a.extra:
revs.append("dir:" + str(Path(a.extra).resolve()))
(work / "commits.txt").write_text("\n".join(revs) + "\n")
data = work / "data"
citm = json.loads((data / "citm_catalog.json").read_text(encoding="utf-8"))
(data / "citm_compact.json").write_text(json.dumps(citm, separators=(",", ":"), ensure_ascii=False), encoding="utf-8")
with concurrent.futures.ThreadPoolExecutor(os.cpu_count()) as ex:
for r in ex.map(lambda p: build_one(work, "%03d" % p[0], p[1], repo), enumerate(revs)):
if r:
print(r, file=sys.stderr)
def load():
out = subprocess.run(["sysctl", "-n", "vm.loadavg"], capture_output=True, text=True).stdout
return float(out.split()[1]) if out else os.getloadavg()[0]
def run(a):
work = Path(a.work)
(work / "res").mkdir(exist_ok=True)
bins = sorted(p.name for p in (work / "bin").iterdir())
for r in range(1, a.rounds + 1):
random.shuffle(bins)
for b in bins:
while load() >= 4:
time.sleep(15)
out = subprocess.run([str(work / "bin" / b), str(work / "data")], check=True, capture_output=True, text=True)
(work / "res" / ("%s-%d.txt" % (b, r))).write_text(out.stdout)
print("round %d done" % r, file=sys.stderr)
def summarize(a):
work = Path(a.work)
revs = (work / "commits.txt").read_text().split()
times, names = {}, []
for f in sorted((work / "res").glob("*.txt")):
idx = int(f.name.split("-")[0])
for line in f.read_text().splitlines():
name, us = line.split()
if name not in names:
names.append(name)
times.setdefault((idx, name), []).append(float(us))
w = csv.writer(sys.stdout, lineterminator="\n")
w.writerow(["index", "commit", "date", "pr", "subject"] + names)
for idx, rev in enumerate(revs):
if rev.startswith("dir:"):
sha, date, pr, subject = "candidate", "", "", "develop + open pull requests"
else:
sha, date, subject = git(a.repo, "log", "-1", "--format=%h%x09%cs%x09%s", rev).strip().split("\t")
m = re.search(r"\(#(\d+)\)$", subject)
pr = m.group(1) if m else ""
w.writerow([idx, sha, date, pr, subject] +
["%.3f" % statistics.median(times[(idx, n)]) if (idx, n) in times else "" for n in names])
def main():
p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
sub = p.add_subparsers(dest="cmd", required=True)
b = sub.add_parser("build")
b.add_argument("--repo", required=True)
b.add_argument("--work", required=True)
b.add_argument("--from", default="v3.12.0")
b.add_argument("--to", default="origin/develop")
b.add_argument("--extra")
r = sub.add_parser("run")
r.add_argument("--work", required=True)
r.add_argument("--rounds", type=int, default=4)
s = sub.add_parser("summarize")
s.add_argument("--work", required=True)
s.add_argument("--repo", default=str(HERE.parents[2]))
a = p.parse_args()
{"build": build, "run": run, "summarize": summarize}[a.cmd](a)
if __name__ == "__main__":
main()