Skip to content

docs: document the complexity of ordered_map operations - #5353

Merged
nlohmann merged 2 commits into
developfrom
claude/todo-239-ordered-map-complexity
Aug 4, 2026
Merged

docs: document the complexity of ordered_map operations#5353
nlohmann merged 2 commits into
developfrom
claude/todo-239-ordered-map-complexity

Conversation

@nlohmann

@nlohmann nlohmann commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary

ordered_map stores its elements in a std::vector in insertion order and keeps no lookup index, so every key-based operation — emplace, operator[], at, find, count, erase, insert — is a linear scan over the elements inserted so far. The documentation stated no complexity at all: neither ordered_map.md nor ordered_json.md said anything about it, and features/object_order.md recommends ordered_json without mentioning the cost.

This PR documents the current behavior. It changes no code.

  • api/ordered_map.md — new Complexity section with a per-operation table, an explicit contrast with std::map's O(log n), and a warning that building an object of n keys is therefore O(n²).
  • api/ordered_json.md — short Complexity section pointing at that table.
  • features/object_order.md — one paragraph next to the existing tsl::ordered_map / fifo_map suggestions, noting that those alternatives keep a lookup index and do not have this cost.

Measurements

Parsing a flat object {"k0":0,"k1":1,…} of n keys, -O2 -DNDEBUG, median of repeated runs, ordered_json vs. json:

n json ordered_json factor
2000 0.7 ms 3.6 ms
4000 0.8 ms 14.0 ms 19×
8000 1.6 ms 67.8 ms 43×
16 000 3.3 ms 181.6 ms 54×

The ordered_json timings quadruple per doubling of n while json roughly doubles — textbook quadratic. Parsing is affected because the SAX builder inserts each key as it is read.

Non-goals

Making lookups sub-linear (e.g. by keeping a side index inside ordered_map) would change sizeof(ordered_map) and is therefore ABI-visible, so it is a separate decision and not attempted here. The complexity is worth writing down either way.

Breaking changes to the public API

None — documentation only, no code or headers touched.


This pull request was prepared by Claude Code.

ordered_map stores its elements in a std::vector in insertion order and
has no lookup index, so emplace, operator[], at, find, count, erase, and
insert are all linear scans. The documentation stated no complexity for
any operation, neither in ordered_map.md nor in ordered_json.md.

Add a per-operation complexity table and note the consequence: building
or parsing an ordered_json object of n keys is O(n^2). Measured with
-O2 -DNDEBUG for parsing a flat object of n keys, ordered_json is 5x
slower than json at n=2000 and 54x slower at n=16000, with the timings
quadrupling per doubling of n. Cross-reference the table from
ordered_json.md and from the object order page, which recommends
ordered_json without mentioning the cost.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
@nlohmann nlohmann added this to the Release 3.13.0 milestone Aug 3, 2026
@nlohmann nlohmann added the 🚀 ready to merge Ready to merge - just waiting for CI to complete. label Aug 3, 2026
scripts/check_structure.py enforces a fixed section order for pages under
docs/mkdocs/docs/api, in which Complexity comes after Member functions.
The section had been placed right after Iterator invalidation, which made
ci_test_build_documentation fail with structure/section_order.

No content change beyond the move; the table columns are realigned to the
narrower content.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
@nlohmann
nlohmann merged commit c2e1cc5 into develop Aug 4, 2026
147 of 155 checks passed
@nlohmann
nlohmann deleted the claude/todo-239-ordered-map-complexity branch August 4, 2026 06:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation M 🚀 ready to merge Ready to merge - just waiting for CI to complete.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants