Skip to content

Document the benchmarks, make them build and compare versions again, and pin Google Benchmark - #5556

Merged
nlohmann merged 3 commits into
developfrom
claude/benchmark-docs
Sep 25, 2026
Merged

nlohmann merged 3 commits into
developfrom
claude/benchmark-docs

Conversation

@nlohmann

@nlohmann nlohmann commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

What & why

tests/benchmarks/ had no documentation, no way to compare two versions, and, as it turned out, didn't build:

  • The benchmark project hasn't configured since Detect used C++ standard library #4793 (May 2025). cmake/download_test_data.cmake compiles detect_libcpp_version.cpp from ${CMAKE_SOURCE_DIR}/cmake/. When tests/benchmarks is the top-level project, that path doesn't exist, so try_run fails and make run_benchmarks stops at configure time.
  • Dump discarded dump()'s result, which is [[nodiscard]] by now. That warns, and it leaves the optimizer free to shorten the measured loop.
  • Comparing versions meant building each version's own benchmarks from scratch. That compares different benchmark code, too.
  • ci_benchmarks in cmake/ci.cmake has configured ${PROJECT_SOURCE_DIR}/benchmarks since CI targets #2561, but the benchmarks live in tests/benchmarks.
  • Google Benchmark was fetched from its main branch, so builds on different days could measure with different library code. CMake 3.30 and later also warn that the single-argument FetchContent_Populate() is deprecated.

The change

  • download_test_data.cmake takes the source from ${CMAKE_CURRENT_LIST_DIR}, the directory of the module itself. For the main build that is the same file as before; its configure still detects the standard library.

  • Dump keeps the result with benchmark::DoNotOptimize.

  • ci_benchmarks points at tests/benchmarks.

  • Google Benchmark is pinned to release 1.9.5. CMake fetches the release archive, checks its SHA-256, and uses FetchContent_MakeAvailable(), which needs CMake 3.14 (Google Benchmark itself already needed 3.13). Its -Werror is off, so a newer compiler's new warnings can't break the pinned release, and its install rules are no longer added.

  • A cache variable, JSON_BENCHMARK_INCLUDE_DIR, names the directory holding the nlohmann/json.hpp to benchmark. It defaults to single_include, as before, so the same benchmarks can be built against two headers.

  • tests/benchmarks/README.md covers:

    • what is measured and what's needed to build it;
    • how to run everything or a selection, and the useful options;
    • how to read the output;
    • how to compare two versions with Google Benchmark's compare.py, and how to get stable numbers.

    It suggests running the comparison by hand before a release and for performance PRs, but not in CI, where shared runners are too noisy.

Verification

  • The README's commands run as written, apart from a --benchmark_filter to keep the run short. Both builds configure (one downloading the test data, one reusing it), build without warnings, and run; compare.py compares the two result files.
  • The current benchmarks build against 3.12.0's header. For example, on this machine develop parses twitter.json 47% faster than 3.12.0 (p = 0.0002, 10 repetitions each).
  • With the pinned release, a fresh configure with CMake 4.3.4 prints no warnings (the old FetchContent_Populate deprecation warning is gone). The benchmarks build with Apple clang and GCC 16, and the compare recipe runs end to end, including v1.9.5's pinned tools/requirements.txt on Python 3.11.
  • The main project still configures and detects libc++. With JSON_CI=ON, the ci_benchmarks target's command now names tests/benchmarks.

Public API impact

No breaking changes. This touches only the benchmark project, its docs, and the CMake module's path to a helper file. Building the benchmarks now needs CMake 3.14 instead of the nominal 3.11.


  • 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. (no library code changed)
  • If applicable, the documentation is updated.
  • The source code is amalgamated by running make amalgamate. (not applicable)

🤖 Generated with Claude Code

The benchmark project hasn't configured since #4793: download_test_data.cmake
compiles cmake/detect_libcpp_version.cpp relative to CMAKE_SOURCE_DIR, which
is tests/benchmarks when that is the top-level project, so try_run fails and
so does `make run_benchmarks`. The path is now relative to the module itself,
which is the same file for the main build.

The Dump benchmark discarded dump()'s result, which is [[nodiscard]] by now;
it warned, and left the optimizer free to shorten the loop. The result is
now kept with benchmark::DoNotOptimize.

A new cache variable, JSON_BENCHMARK_INCLUDE_DIR, names the directory holding
the nlohmann/json.hpp to benchmark (single_include by default, as before),
so the same benchmarks can be built against two versions and compared.

tests/benchmarks/README.md documents what is measured, how to build and run
the benchmarks, how to read the output, and how to compare two versions with
Google Benchmark's compare.py; it recommends doing so by hand before a
release rather than in CI.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
The target has configured ${PROJECT_SOURCE_DIR}/benchmarks since it was
added in #2561, but the benchmarks live in tests/benchmarks.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
@nlohmann nlohmann added the review needed It would be great if someone could review the proposed changes. label Sep 24, 2026
The benchmarks fetched Google Benchmark's main branch, so two builds on
different days could measure with different library code, and CMake 3.30
and later warn that the single-argument FetchContent_Populate() is
deprecated. Fetch the 1.9.5 release archive, verified by its SHA-256,
with FetchContent_MakeAvailable() instead. That needs CMake 3.14; Google
Benchmark itself already needed 3.13.

Its -Werror is switched off, so a newer compiler's new warnings cannot
break the pinned release, and its install rules are no longer added.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
@nlohmann nlohmann changed the title Document the benchmarks, and make them build and compare versions again Document the benchmarks, make them build and compare versions again, and pin Google Benchmark Sep 24, 2026
@nlohmann nlohmann added this to the Release 3.13.0 milestone Sep 25, 2026
@nlohmann
nlohmann merged commit ec4bdc3 into develop Sep 25, 2026
162 checks passed
@nlohmann
nlohmann deleted the claude/benchmark-docs branch September 25, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CMake documentation L review needed It would be great if someone could review the proposed changes. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant