[libcxx-commits] [libcxx] [libc++] Rewrite the std::lower_bound benchmark to be more efficient and add an upper_bound benchmark (PR #177180)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jan 27 01:23:51 PST 2026


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/177180

>From 52730e3ca01940b65f19fdbb283f8eb151d4c5bd Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 21 Jan 2026 15:41:43 +0100
Subject: [PATCH] [libc++] Rewrite the std::lower_bound benchmark to be more
 efficient and add an upper_bound benchmark

---
 .../algorithms/lower_bound.bench.cpp          | 42 ---------
 .../nonmodifying/lower_upper_bound.bench.cpp  | 86 +++++++++++++++++++
 2 files changed, 86 insertions(+), 42 deletions(-)
 delete mode 100644 libcxx/test/benchmarks/algorithms/lower_bound.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/nonmodifying/lower_upper_bound.bench.cpp

diff --git a/libcxx/test/benchmarks/algorithms/lower_bound.bench.cpp b/libcxx/test/benchmarks/algorithms/lower_bound.bench.cpp
deleted file mode 100644
index 31fb3597241fc..0000000000000
--- a/libcxx/test/benchmarks/algorithms/lower_bound.bench.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <algorithm>
-#include <numeric>
-#include <random>
-#include <vector>
-
-#include "common.h"
-
-namespace {
-template <class ValueType>
-struct LowerBound {
-  size_t Quantity;
-
-  mutable std::mt19937_64 rng{std::random_device{}()};
-
-  void run(benchmark::State& state) const {
-    runOpOnCopies<ValueType>(state, Quantity, Order::Ascending, BatchSize::CountBatch, [&](auto& Copy) {
-      auto result = std::lower_bound(Copy.begin(), Copy.end(), Copy[rng() % Copy.size()]);
-      benchmark::DoNotOptimize(result);
-    });
-  }
-
-  std::string name() const { return "BM_LowerBound" + ValueType::name() + "_" + std::to_string(Quantity); }
-};
-} // namespace
-
-int main(int argc, char** argv) {
-  benchmark::Initialize(&argc, argv);
-  if (benchmark::ReportUnrecognizedArguments(argc, argv))
-    return 1;
-  makeCartesianProductBenchmark<LowerBound, AllValueTypes>(Quantities);
-  benchmark::RunSpecifiedBenchmarks();
-}
diff --git a/libcxx/test/benchmarks/algorithms/nonmodifying/lower_upper_bound.bench.cpp b/libcxx/test/benchmarks/algorithms/nonmodifying/lower_upper_bound.bench.cpp
new file mode 100644
index 0000000000000..16ef348539776
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/nonmodifying/lower_upper_bound.bench.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+#include <algorithm>
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+int main(int argc, char** argv) {
+  {
+    auto bm = []<class Container>(benchmark::State& state) static {
+      std::mt19937_64 rng{123456};
+
+      using value_type = typename Container::value_type;
+
+      std::vector<value_type> vec;
+      for (int64_t i = 0; i != state.range(); ++i)
+        vec.emplace_back(Generate<typename Container::value_type>::random());
+      std::sort(vec.begin(), vec.end());
+
+      Container c(vec.begin(), vec.end());
+
+      for (auto _ : state) {
+        auto result = std::lower_bound(c.begin(), c.end(), vec[rng() % vec.size()]);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(vec);
+      }
+    };
+
+    auto register_benchmark = [&]<class Container>(std::type_identity<Container>, std::string name) {
+      benchmark::RegisterBenchmark(name, bm.template operator()<Container>)->Arg(8)->Arg(100)->Arg(8192);
+    };
+
+    register_benchmark(std::type_identity<std::vector<int>>{}, "std::lower_bound(std::vector<int>)");
+    register_benchmark(std::type_identity<std::deque<int>>{}, "std::lower_bound(std::deque<int>)");
+    register_benchmark(std::type_identity<std::list<int>>{}, "std::lower_bound(std::list<int>)");
+    register_benchmark(std::type_identity<std::forward_list<int>>{}, "std::lower_bound(std::forward_list<int>)");
+  }
+  {
+    auto bm = []<class Container>(benchmark::State& state) static {
+      std::mt19937_64 rng{123456};
+
+      using value_type = typename Container::value_type;
+
+      std::vector<value_type> vec;
+      for (int64_t i = 0; i != state.range(); ++i)
+        vec.emplace_back(Generate<typename Container::value_type>::random());
+      std::sort(vec.begin(), vec.end());
+
+      Container c(vec.begin(), vec.end());
+
+      for (auto _ : state) {
+        auto result = std::upper_bound(c.begin(), c.end(), vec[rng() % vec.size()]);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(vec);
+      }
+    };
+
+    auto register_benchmark = [&]<class Container>(std::type_identity<Container>, std::string name) {
+      benchmark::RegisterBenchmark(name, bm.template operator()<Container>)->Arg(8)->Arg(100)->Arg(8192);
+    };
+
+    register_benchmark(std::type_identity<std::vector<int>>{}, "std::upper_bound(std::vector<int>)");
+    register_benchmark(std::type_identity<std::deque<int>>{}, "std::upper_bound(std::deque<int>)");
+    register_benchmark(std::type_identity<std::list<int>>{}, "std::upper_bound(std::list<int>)");
+    register_benchmark(std::type_identity<std::forward_list<int>>{}, "std::upper_bound(std::forward_list<int>)");
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}



More information about the libcxx-commits mailing list