Repository navigation
Construct the JSON Patch exceptions out of line - #5842
Merged
nlohmann merged 1 commit intoOct 15, 2026
Merged
Conversation
nlohmann
added this pull request to stack #5841
October 15, 2026 06:33
nlohmann
force-pushed
the
perf/remaining-throw-sites
branch
from
October 15, 2026 08:57
f48141c to
513b7e4
Compare
nlohmann
force-pushed
the
perf/remaining-throw-sites
branch
from
October 15, 2026 09:54
513b7e4 to
7bb0e41
Compare
gregmarr
approved these changes
Oct 15, 2026
nlohmann
force-pushed
the
perf/remaining-throw-sites
branch
from
October 15, 2026 17:41
7bb0e41 to
e4b488a
Compare
nlohmann
force-pushed
the
perf/remaining-throw-sites
branch
from
October 15, 2026 17:43
e4b488a to
75a9259
Compare
nlohmann
force-pushed
the
perf/remaining-throw-sites
branch
from
October 15, 2026 17:45
75a9259 to
0711425
Compare
patch_inplace() built its error messages inline. In particular get_value() concatenated the context-sensitive "operation 'x'" string on every call, even when nothing was wrong. The patch exceptions now come from NEVER_INLINE helpers: the index and key errors reuse basic_json's existing throw_array_index_out_of_range/throw_key_not_found, and the seven patch-specific messages get one helper each in detail/exceptions.hpp. Ids and messages are unchanged, and unit-throw_messages pins them (with and without JSON_DIAGNOSTICS). citm_catalog patch: -6.6 % (Apple clang), -9.5 % (GCC 16). The other remaining throw sites (parser::syntax_error, binary_writer, serializer, input_adapters, enum_key_duplicate, format_error) were prototyped and measured: no gain beyond noise, so they stay as they are. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
nlohmann
force-pushed
the
perf/remaining-throw-sites
branch
from
October 15, 2026 17:54
0711425 to
8c1e549
Compare
This was referenced Oct 15, 2026
nlohmann
added a commit
that referenced
this pull request
Oct 16, 2026
Fixes every CI failure develop has had since the API performance stack (#5831-#5842) was merged: compiler warnings and errors (Clang, GCC 4.9/11, MSVC 2015/2017/2022), clang-tidy, cpplint, Cppcheck, IWYU, the examples check, the no-exceptions, diagnostic-positions, implicit-conversions and strict-NUL test configurations, and the MinGW link (now with LLD). Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
patch_inplace()built its error messages inline. In particular,get_value()concatenated the context-sensitiveoperation 'x'string on every call, even when the member was present. This PR moves the JSON Patch exceptions out of line:basic_json's existingthrow_array_index_out_of_rangeandthrow_key_not_foundfrom Construct remaining hot-path exceptions out of line so core functions inline #5838.NEVER_INLINEhelper indetail/exceptions.hpp: add/remove parent not a container, not an array, missing member, move into child, test failed, invalid operation.get_value()now builds theoperation 'x'string only inside the missing-member helper.Exception ids and messages are byte-identical.
unit-throw_messagesgets apatchsection that pins all 14 messages. It strips the(/0)prefix thatJSON_DIAGNOSTICSadds, so the section passes in both configurations.Measured
patch(diff(a, b))on citm_catalog, best of 9, alternating builds:-O2-O2The GCC numbers come from the all-sites prototype, before it was reduced to the patch sites.
Deliberately left inline
The other exceptions that are still built inline were prototyped together and measured on parse, accept, dump, all binary writers and diff for citm, twitter and canada. Nothing moved beyond noise: ±2.8 % on clang, ±1.5 % on GCC. These sites stay as they are, because they are cold or already behind a call:
parser::syntax_errorbinary_writerandthrow_on_discardedserializerinput_adapters' empty inputto_json'senum_key_duplicateformat_error(std::format parsing)Performance summary of stack #5841
The table compares the top of the stack (this PR, which contains all eleven PRs) with
develop(4e294f4).-O2 -DNDEBUG, arm64) and GCC 16 (-O2 -DNDEBUG, Docker on the same machine).ordered_json::flatten()citmjson::flatten()citmjson_pointer(string)json_pointer::to_string()at(json_pointer)contains(json_pointer)unflatten()citmget<std::vector<int>>, per elementget<vector<vector<vector<double>>>>json(std::move(vector<string>)), 200kJSON_DIAGNOSTICS:ordered_json100kpush_backJSON_DIAGNOSTICS:ordered_json::update(), 20k keysJSON_DIAGNOSTICS: copy citmjsonj == 5std::vector<json>of 1M ints, build + destroy==canadaget_ref<const std::string&>()at(i)arr[i]std::sortof 1M json intsdiff({}, citm)parse()citm with callbackfrom_cbor/from_msgpack/from_ubjson/from_bsoncitmfrom_bjdatatwitterpatch(diff(a, b))citm¹ The rest is
ordered_map's linear key lookup, not the diagnostics. WithoutJSON_DIAGNOSTICSthe sameupdate()takes 269 ms on clang. The diagnostics overhead on top of it dropped from about 37 % to about 20 %.Regression guard, parse/accept/dump on all three documents:
Slower on GCC, small:
citm == citm+3 %,diff(citm, citm)+4 %,ordered_jsonparse of citm withJSON_DIAGNOSTICS+3 %. The clang run-to-run spread on these rows is 2–8 %. #5840 describes the GCC==effect on large documents.The benchmark source is standalone (one
.cppfile, no Google Benchmark) and can be posted on request.Breaking changes
No breaking changes. The new helpers are in
nlohmann::detail, and exception types, ids and messages are unchanged.🤖 Generated with Claude Code