Skip to content

[libc++] Refactor and add benchmarks from [alg.nonmodifying] #128206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Mar 19, 2025

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Feb 21, 2025

No description provided.

@ldionne ldionne requested a review from a team as a code owner February 21, 2025 17:20
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 21, 2025

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

Patch is 109.56 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128206.diff

26 Files Affected:

  • (modified) libcxx/test/benchmarks/GenerateInput.h (+10)
  • (removed) libcxx/test/benchmarks/algorithms/count.bench.cpp (-37)
  • (removed) libcxx/test/benchmarks/algorithms/equal.bench.cpp (-48)
  • (removed) libcxx/test/benchmarks/algorithms/find.bench.cpp (-90)
  • (removed) libcxx/test/benchmarks/algorithms/for_each.bench.cpp (-25)
  • (removed) libcxx/test/benchmarks/algorithms/mismatch.bench.cpp (-58)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/adjacent_find.bench.cpp (+87)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/any_all_none_of.bench.cpp (+152)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/contains.bench.cpp (+80)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/contains_subrange.bench.cpp (+82)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/count.bench.cpp (+156)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/ends_with.bench.cpp (+104)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/equal.bench.cpp (+106)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/find.bench.cpp (+179)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/find_end.bench.cpp (+102)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/find_first_of.bench.cpp (+115)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/find_last.bench.cpp (+134)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/fold.bench.cpp (+76)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/for_each.bench.cpp (+57)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/is_permutation.bench.cpp (+157)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/mismatch.bench.cpp (+111)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/search.bench.cpp (+137)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/search_n.bench.cpp (+138)
  • (added) libcxx/test/benchmarks/algorithms/nonmodifying/starts_with.bench.cpp (+69)
  • (removed) libcxx/test/benchmarks/algorithms/ranges_contains.bench.cpp (-51)
  • (removed) libcxx/test/benchmarks/algorithms/ranges_ends_with.bench.cpp (-109)
diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h
index c87fd69162e9d..6fc54f731e094 100644
--- a/libcxx/test/benchmarks/GenerateInput.h
+++ b/libcxx/test/benchmarks/GenerateInput.h
@@ -13,6 +13,7 @@
 #include <climits>
 #include <concepts>
 #include <cstddef>
+#include <initializer_list>
 #include <random>
 #include <string>
 #include <vector>
@@ -204,4 +205,13 @@ struct Generate<std::string> {
   }
 };
 
+template <class T>
+T random_different_from(std::initializer_list<T> others) {
+  T value;
+  do {
+    value = Generate<T>::random();
+  } while (std::ranges::contains(others, value));
+  return value;
+}
+
 #endif // BENCHMARK_GENERATE_INPUT_H
diff --git a/libcxx/test/benchmarks/algorithms/count.bench.cpp b/libcxx/test/benchmarks/algorithms/count.bench.cpp
deleted file mode 100644
index 46b85e909efa5..0000000000000
--- a/libcxx/test/benchmarks/algorithms/count.bench.cpp
+++ /dev/null
@@ -1,37 +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 <benchmark/benchmark.h>
-#include <cstring>
-#include <random>
-#include <vector>
-
-static void bm_vector_bool_count(benchmark::State& state) {
-  std::vector<bool> vec1(state.range(), false);
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::count(vec1.begin(), vec1.end(), true));
-  }
-}
-BENCHMARK(bm_vector_bool_count)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_vector_bool_ranges_count(benchmark::State& state) {
-  std::vector<bool> vec1(state.range(), false);
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::ranges::count(vec1.begin(), vec1.end(), true));
-  }
-}
-BENCHMARK(bm_vector_bool_ranges_count)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/equal.bench.cpp b/libcxx/test/benchmarks/algorithms/equal.bench.cpp
deleted file mode 100644
index 2dc11585c15c7..0000000000000
--- a/libcxx/test/benchmarks/algorithms/equal.bench.cpp
+++ /dev/null
@@ -1,48 +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 <benchmark/benchmark.h>
-#include <vector>
-
-static void bm_equal_iter(benchmark::State& state) {
-  std::vector<char> vec1(state.range(), '1');
-  std::vector<char> vec2(state.range(), '1');
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(vec2);
-    benchmark::DoNotOptimize(std::equal(vec1.begin(), vec1.end(), vec2.begin()));
-  }
-}
-BENCHMARK(bm_equal_iter)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_equal(benchmark::State& state) {
-  std::vector<char> vec1(state.range(), '1');
-  std::vector<char> vec2(state.range(), '1');
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(vec2);
-    benchmark::DoNotOptimize(std::equal(vec1.begin(), vec1.end(), vec2.begin(), vec2.end()));
-  }
-}
-BENCHMARK(bm_equal)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_ranges_equal(benchmark::State& state) {
-  std::vector<char> vec1(state.range(), '1');
-  std::vector<char> vec2(state.range(), '1');
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(vec2);
-    benchmark::DoNotOptimize(std::ranges::equal(vec1, vec2));
-  }
-}
-BENCHMARK(bm_ranges_equal)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/find.bench.cpp b/libcxx/test/benchmarks/algorithms/find.bench.cpp
deleted file mode 100644
index 43d103474ebdf..0000000000000
--- a/libcxx/test/benchmarks/algorithms/find.bench.cpp
+++ /dev/null
@@ -1,90 +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 <benchmark/benchmark.h>
-#include <cstring>
-#include <deque>
-#include <random>
-#include <vector>
-
-template <class Container>
-static void bm_find(benchmark::State& state) {
-  using T = Container::value_type;
-
-  Container vec1(state.range(), '1');
-  std::mt19937_64 rng(std::random_device{}());
-
-  for (auto _ : state) {
-    auto idx  = rng() % vec1.size();
-    vec1[idx] = '2';
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::find(vec1.begin(), vec1.end(), T('2')));
-    vec1[idx] = '1';
-  }
-}
-BENCHMARK(bm_find<std::vector<char>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_find<std::vector<short>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_find<std::vector<int>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_find<std::deque<char>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_find<std::deque<short>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_find<std::deque<int>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-template <class Container>
-static void bm_ranges_find(benchmark::State& state) {
-  using T = Container::value_type;
-
-  Container vec1(state.range(), '1');
-  std::mt19937_64 rng(std::random_device{}());
-
-  for (auto _ : state) {
-    auto idx  = rng() % vec1.size();
-    vec1[idx] = '2';
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::ranges::find(vec1, T('2')));
-    vec1[idx] = '1';
-  }
-}
-BENCHMARK(bm_ranges_find<std::vector<char>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_ranges_find<std::vector<short>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_ranges_find<std::vector<int>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_ranges_find<std::deque<char>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_ranges_find<std::deque<short>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_ranges_find<std::deque<int>>)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_vector_bool_find(benchmark::State& state) {
-  std::vector<bool> vec1(state.range(), false);
-  std::mt19937_64 rng(std::random_device{}());
-
-  for (auto _ : state) {
-    auto idx  = rng() % vec1.size();
-    vec1[idx] = true;
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::find(vec1.begin(), vec1.end(), true));
-    vec1[idx] = false;
-  }
-}
-BENCHMARK(bm_vector_bool_find)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_vector_bool_ranges_find(benchmark::State& state) {
-  std::vector<bool> vec1(state.range(), false);
-  std::mt19937_64 rng(std::random_device{}());
-
-  for (auto _ : state) {
-    auto idx  = rng() % vec1.size();
-    vec1[idx] = true;
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::ranges::find(vec1, true));
-    vec1[idx] = false;
-  }
-}
-BENCHMARK(bm_vector_bool_ranges_find)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/for_each.bench.cpp b/libcxx/test/benchmarks/algorithms/for_each.bench.cpp
deleted file mode 100644
index 554c9ec993043..0000000000000
--- a/libcxx/test/benchmarks/algorithms/for_each.bench.cpp
+++ /dev/null
@@ -1,25 +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
-
-#include <algorithm>
-#include <benchmark/benchmark.h>
-#include <deque>
-
-static void bm_deque_for_each(benchmark::State& state) {
-  std::deque<char> vec1(state.range(), '1');
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(
-        std::for_each(vec1.begin(), vec1.end(), [](char& v) { v = std::clamp(v, (char)10, (char)100); }));
-  }
-}
-BENCHMARK(bm_deque_for_each)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/mismatch.bench.cpp b/libcxx/test/benchmarks/algorithms/mismatch.bench.cpp
deleted file mode 100644
index 348009a230d6e..0000000000000
--- a/libcxx/test/benchmarks/algorithms/mismatch.bench.cpp
+++ /dev/null
@@ -1,58 +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
-
-#include <algorithm>
-#include <benchmark/benchmark.h>
-#include <random>
-
-void BenchmarkSizes(benchmark::internal::Benchmark* Benchmark) {
-  Benchmark->DenseRange(1, 8);
-  for (size_t i = 16; i != 1 << 20; i *= 2) {
-    Benchmark->Arg(i - 1);
-    Benchmark->Arg(i);
-    Benchmark->Arg(i + 1);
-  }
-}
-
-// TODO: Look into benchmarking aligned and unaligned memory explicitly
-// (currently things happen to be aligned because they are malloced that way)
-template <class T>
-static void bm_mismatch(benchmark::State& state) {
-  std::vector<T> vec1(state.range(), '1');
-  std::vector<T> vec2(state.range(), '1');
-  std::mt19937_64 rng(std::random_device{}());
-
-  vec1.back() = '2';
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::mismatch(vec1.begin(), vec1.end(), vec2.begin()));
-  }
-}
-BENCHMARK(bm_mismatch<char>)->Apply(BenchmarkSizes);
-BENCHMARK(bm_mismatch<short>)->Apply(BenchmarkSizes);
-BENCHMARK(bm_mismatch<int>)->Apply(BenchmarkSizes);
-
-template <class T>
-static void bm_mismatch_two_range_overload(benchmark::State& state) {
-  std::vector<T> vec1(state.range(), '1');
-  std::vector<T> vec2(state.range(), '1');
-  std::mt19937_64 rng(std::random_device{}());
-
-  vec1.back() = '2';
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::mismatch(vec1.begin(), vec1.end(), vec2.begin(), vec2.end()));
-  }
-}
-BENCHMARK(bm_mismatch_two_range_overload<char>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_mismatch_two_range_overload<short>)->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_mismatch_two_range_overload<int>)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/nonmodifying/adjacent_find.bench.cpp b/libcxx/test/benchmarks/algorithms/nonmodifying/adjacent_find.bench.cpp
new file mode 100644
index 0000000000000..1f6e20dfa4527
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/nonmodifying/adjacent_find.bench.cpp
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <cstddef>
+#include <deque>
+#include <list>
+#include <string>
+#include <vector>
+
+#include <benchmark/benchmark.h>
+#include "../../GenerateInput.h"
+
+int main(int argc, char** argv) {
+  auto std_adjacent_find      = [](auto first, auto last) { return std::adjacent_find(first, last); };
+  auto std_adjacent_find_pred = [](auto first, auto last) {
+    return std::adjacent_find(first, last, [](auto x, auto y) {
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(y);
+      return x == y;
+    });
+  };
+  auto ranges_adjacent_find_pred = [](auto first, auto last) {
+    return std::ranges::adjacent_find(first, last, [](auto x, auto y) {
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(y);
+      return x == y;
+    });
+  };
+
+  // Benchmark {std,ranges}::adjacent_find on a sequence of the form xyxyxyxyxyxyxyxyxyxy,
+  // which means we never find adjacent equal elements (the worst case of the algorithm).
+  {
+    auto bm = []<class Container>(std::string name, auto adjacent_find) {
+      benchmark::RegisterBenchmark(
+          name,
+          [adjacent_find](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            ValueType x            = Generate<ValueType>::random();
+            ValueType y            = random_different_from({x});
+            Container c;
+            for (std::size_t i = 0; i != size; ++i) {
+              c.push_back(i % 2 == 0 ? x : y);
+            }
+
+            for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              auto result = adjacent_find(c.begin(), c.end());
+              benchmark::DoNotOptimize(result);
+            }
+          })
+          ->Arg(8)
+          ->Arg(1024)
+          ->Arg(8192)
+          ->Arg(1 << 20);
+    };
+
+    // {std,ranges}::adjacent_find
+    bm.operator()<std::vector<int>>("std::adjacent_find(vector<int>)", std_adjacent_find);
+    bm.operator()<std::deque<int>>("std::adjacent_find(deque<int>)", std_adjacent_find);
+    bm.operator()<std::list<int>>("std::adjacent_find(list<int>)", std_adjacent_find);
+    bm.operator()<std::vector<int>>("rng::adjacent_find(vector<int>)", std::ranges::adjacent_find);
+    bm.operator()<std::deque<int>>("rng::adjacent_find(deque<int>)", std::ranges::adjacent_find);
+    bm.operator()<std::list<int>>("rng::adjacent_find(list<int>)", std::ranges::adjacent_find);
+
+    // {std,ranges}::adjacent_find(pred)
+    bm.operator()<std::vector<int>>("std::adjacent_find(vector<int>, pred)", std_adjacent_find_pred);
+    bm.operator()<std::deque<int>>("std::adjacent_find(deque<int>, pred)", std_adjacent_find_pred);
+    bm.operator()<std::list<int>>("std::adjacent_find(list<int>, pred)", std_adjacent_find_pred);
+    bm.operator()<std::vector<int>>("rng::adjacent_find(vector<int>, pred)", ranges_adjacent_find_pred);
+    bm.operator()<std::deque<int>>("rng::adjacent_find(deque<int>, pred)", ranges_adjacent_find_pred);
+    bm.operator()<std::list<int>>("rng::adjacent_find(list<int>, pred)", ranges_adjacent_find_pred);
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/nonmodifying/any_all_none_of.bench.cpp b/libcxx/test/benchmarks/algorithms/nonmodifying/any_all_none_of.bench.cpp
new file mode 100644
index 0000000000000..363ed96f6d201
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/nonmodifying/any_all_none_of.bench.cpp
@@ -0,0 +1,152 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <cstddef>
+#include <deque>
+#include <list>
+#include <numeric>
+#include <string>
+#include <vector>
+
+#include <benchmark/benchmark.h>
+#include "../../GenerateInput.h"
+
+int main(int argc, char** argv) {
+  auto std_any_of = [](auto first, auto last, auto pred) { return std::any_of(first, last, pred); };
+  auto std_all_of = [](auto first, auto last, auto pred) {
+    // match semantics of any_of
+    return !std::all_of(first, last, [pred](auto x) { return !pred(x); });
+  };
+  auto std_none_of = [](auto first, auto last, auto pred) {
+    // match semantics of any_of
+    return !std::none_of(first, last, pred);
+  };
+
+  auto ranges_all_of = [](auto first, auto last, auto pred) {
+    // match semantics of any_of
+    return !std::ranges::all_of(first, last, [pred](auto x) { return !pred(x); });
+  };
+  auto ranges_none_of = [](auto first, auto last, auto pred) {
+    // match semantics of any_of
+    return !std::ranges::none_of(first, last, pred);
+  };
+
+  // Benchmark {std,ranges}::{any_of,all_of,none_of} where we bail out early
+  // (after visiting 25% of the elements).
+  {
+    auto bm = []<class Container>(std::string name, auto any_of) {
+      benchmark::RegisterBenchmark(
+          name,
+          [any_of](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            ValueType x            = Generate<ValueType>::random();
+            ValueType y            = random_different_from({x});
+            Container c(size, x);
+            *std::next(c.begin(), size / 4) = y; // bail out after the first 25% elements
+
+            for (auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              auto result = any_of(c.begin(), c.end(), [&](auto element) {
+                benchmark::DoNotOptimize(element);
+                return element == y;
+              });
+              benchmark::DoNotOptimize(result);
+            }
+          })
+          ->Arg(8)
+          ->Arg(32)
+          ->Arg(8192)
+          ->Arg(32768);
+    };
+
+    // any_of
+    bm.operator()<std::vector<int>>("std::any_of(vector<int>) (bail 25%)", std_any_of);
+    bm.operator()<std::deque<int>>("std::any_of(deque<int>) (bail 25%)", std_any_of);
+    bm.operator()<std::list<int>>("std::any_of(list<int>) (bail 25%)", std_any_of);
+    bm.operator()<std::vector<int>>("rng::any_of(vector<int>) (bail 25%)", std::ranges::any_of);
+    bm.operator()<std::deque<int>>("rng::any_of(deque<int>) (bail 25%)", std::ranges::any_of);
+    bm.operator()<std::list<int>>("rng::any_of(list<int>) (bail 25%)", std::ranges::any_of);
+
+    // all_of
+    bm.operator()<std::vector<int>>("std::all_of(vector<int>) (bail 25%)", std_all_of);
+    bm.operator()<std::deque<int>>("std::all_of(deque<int>) (bail 25%)", std_all_of);
+    bm.operator()<std::list<int>>("std::all_of(list<int>) (bail 25%)", std_all_of);
+    bm.operator()<std::vector<int>>("rng::all_of(vector<int>) (bail 25%)", ranges_all_of);
+    bm.operator()<std::deque<int>>("rng::all_of(deque<int>) (bail 25%)", ranges_all_of);
+    bm.operator()<std::list<int>>("rng::all_of(list<int>) (bail 25%)", ranges_all_of);
+
+    // none_of
+    bm.operator()<std::vector<int>>("std::none_of(vector<int>) (bail 25%)", std_none_of);
+    bm.operator()<std::deque<int>>("std::none_of(deque<int>) (bail 25%)", std_none_of);
+    bm.operator()<std::list<int>>("std::none_of(list<int>) (bail 25%)", std_none_of);
+    bm.operator()<std::vector<int>>("rng::none_of(vector<int>) (bail 25%)", ranges_none_of);
+    bm.operator()<std::deque<int>>("rng::none_of(deque<int>) (bail 25%)", ranges_none_of);
+    bm.operator()<std::list<int>>("rng::none_of(list<int>) (bail 25%)", ranges_none_of);
+  }
+
+  // Benchmark {std,ranges}::{any_of,all_of,none_of} where we process the whole sequence.
+  {
+    auto bm = []<class Container>(std::string name, auto any_of) {
+      benchmark::RegisterBenchmark(
+          name,
+          [any_of](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            ValueType x            = Generate<ValueType>::random();
+            ValueType y            = random_different_from({x});
+            ...
[truncated]

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for working on this! LGTM!

@ldionne ldionne force-pushed the review/benchmarks-add-nonmodifying branch from eca6125 to 2162665 Compare March 17, 2025 14:08
@ldionne ldionne force-pushed the review/benchmarks-add-nonmodifying branch from 0512a04 to e8c40d4 Compare March 18, 2025 02:44
@ldionne
Copy link
Member Author

ldionne commented Mar 19, 2025

Same here, I'm going to land this now since I've applied pretty much all review feedback, but it could make sense to make another pass over this once you're back from vacation, @philnik777 .

@ldionne ldionne merged commit b3a4bf9 into llvm:main Mar 19, 2025
86 checks passed
@ldionne ldionne deleted the review/benchmarks-add-nonmodifying branch March 19, 2025 04:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants