[libcxx-commits] [libcxx] [libc++] Fix query benchmarks for associative containers (PR #216065)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 13 07:26:24 PDT 2026
https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/216065
We were calling get_key and the random number generator in the hot loop. Instead, create a pool of keys to draw from in the initial setup phase, and then query these keys in a round-robin fashion.
>From 5241b359e1babaf0e39f94d698c06cc28ca9fb70 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 13 Aug 2026 09:42:26 -0400
Subject: [PATCH] [libc++] Fix query benchmarks for associative containers
We were calling get_key and the random number generator in the hot loop.
Instead, create a pool of keys to draw from in the initial setup phase,
and then query these keys in a round-robin fashion.
---
.../associative_container_benchmarks.h | 26 +++++++++++++++----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
index 34cd1ca90b647..d83c8db9c3ad5 100644
--- a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
+++ b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
@@ -706,12 +706,28 @@ void associative_container_benchmarks(std::string container) {
/////////////////////////
auto query_bench = [=](auto func) {
return [=](auto& st) TEST_ALIGN_BENCHMARK {
- const std::size_t size = st.range(0);
- std::vector<Value> in = make_value_types(generate_unique_keys(size));
- Container c(in.begin(), in.end());
-
+ const std::size_t size = st.range(0);
+ std::vector<Key> keys = generate_unique_keys(size);
+ std::vector<Value> values = make_value_types(keys);
+ Container c(values.begin(), values.end());
+
+ // Create a pool of key indices to draw in the benchmark below. Make the
+ // pool large enough to defeat a branch predictor even when benchmarking
+ // small sizes.
+ const std::size_t N_DRAWS = std::max<std::size_t>(4096, keys.size());
+ std::vector<std::size_t> draws;
+ draws.reserve(N_DRAWS);
+ for (std::size_t i = 0; i != N_DRAWS; ++i) {
+ draws.push_back(getRandomEngine()() % keys.size());
+ }
+
+ std::size_t i = 0;
for (auto _ : st) {
- auto result = func(c, get_key(in[getRandomEngine()() % in.size()]));
+ Key const& key = keys[draws[i]];
+ auto result = func(c, key);
+ ++i;
+ if (i == N_DRAWS)
+ i = 0;
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(result);
benchmark::ClobberMemory();
More information about the libcxx-commits
mailing list