[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:28:18 PDT 2026


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/216065

>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 1/2] [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();

>From f2bc6ecbbb2f4fda81ac27a48fe060ee14aa2e3f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 13 Aug 2026 10:27:58 -0400
Subject: [PATCH 2/2] Simplify bounded increment

---
 .../containers/associative/associative_container_benchmarks.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
index d83c8db9c3ad5..5ad18e685952e 100644
--- a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
+++ b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
@@ -725,9 +725,7 @@ void associative_container_benchmarks(std::string container) {
       for (auto _ : st) {
         Key const& key = keys[draws[i]];
         auto result    = func(c, key);
-        ++i;
-        if (i == N_DRAWS)
-          i = 0;
+        i = (i == N_DRAWS ? 0 : i + 1);
         benchmark::DoNotOptimize(c);
         benchmark::DoNotOptimize(result);
         benchmark::ClobberMemory();



More information about the libcxx-commits mailing list