Skip to content

Stop allocating the BJData excluded-marker list per container - #5555

Merged
nlohmann merged 1 commit into
developfrom
claude/bjdata-excluded-markers
Sep 24, 2026
Merged

nlohmann merged 1 commit into
developfrom
claude/bjdata-excluded-markers

Conversation

@nlohmann

Copy link
Copy Markdown
Owner

What & why

write_ubjson() built a std::vector of the eight markers BJData forbids as the type of an optimized container ([, {, S, H, T, F, N, Z). It did so for every array and object it wrote with use_type, one heap allocation and a linear search each, even for plain UBJSON output, which never consults the list. The literal was also spelled out twice, kept in sync only by convention.

The change

A static constexpr helper, is_bjdata_excluded_type_marker(), replaces both vectors and std::find calls. It is the same set the reader rejects (bjd_optimized_type_markers), and nothing else changes.

Verification

  • Byte-identical: a differential against develop over 28,400 outputs (22,720 of them UBJSON/BJData) is identical in C++11 and C++20. It covers json and ordered_json, every use_size/use_type combination, BJData drafts 2 and 3, and the vector and adapter overloads. A mutant that drops S and Z from the helper changes 2,203 of those outputs, so the differential does exercise it.

  • unit-ubjson and unit-bjdata pass. They build cleanly with CI's GCC warning flags in C++11 and C++26, and clang-tidy reports no new findings.

  • Speed (clang -O3, median of 41 runs, 20,000 small typed containers):

    workload develop this PR
    to_ubjson(j, true, true), arrays and objects of numbers 1.71 ms 1.15 ms
    to_bjdata(j, true, true), arrays and objects of numbers 1.76 ms 1.16 ms
    to_ubjson(j, true, true), arrays of strings 1.42 ms 0.91 ms
    to_bjdata(j, true, true), arrays of strings 1.52 ms 0.89 ms

#5518 moves both call sites into new functions; whichever of the two merges second needs a two-line adjustment.

Public API impact

No breaking changes. Same output, and only a private helper was added.


  • The changes are described in detail, both the what and why.
  • If applicable, an existing issue is referenced. (none)
  • The Code coverage remained at 100%. A test case for every new line of code.
  • If applicable, the documentation is updated. (not applicable)
  • The source code is amalgamated by running make amalgamate.

🤖 Generated with Claude Code

write_ubjson() built a std::vector of the eight markers BJData forbids as
the type of an optimized container - one heap allocation plus a linear
search for every array and object it wrote with use_type, even for plain
UBJSON output, where the list isn't consulted. The list was also spelled
out twice. A constexpr helper, is_bjdata_excluded_type_marker(), replaces
both.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
@nlohmann nlohmann added aspect: binary formats BSON, CBOR, MessagePack, UBJSON performance review needed It would be great if someone could review the proposed changes. labels Sep 24, 2026
@github-actions github-actions Bot added the M label Sep 24, 2026
@nlohmann nlohmann removed the review needed It would be great if someone could review the proposed changes. label Sep 24, 2026
@nlohmann nlohmann added this to the Release 3.13.0 milestone Sep 24, 2026
@nlohmann
nlohmann merged commit 8699de3 into develop Sep 24, 2026
161 of 162 checks passed
@nlohmann
nlohmann deleted the claude/bjdata-excluded-markers branch September 24, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aspect: binary formats BSON, CBOR, MessagePack, UBJSON M performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants