[libcxx-commits] [libcxx] 8feb5ba - [libc++] Add benchmarks for copy algorithms (#127328)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Feb 20 05:24:37 PST 2025


Author: Louis Dionne
Date: 2025-02-20T08:24:32-05:00
New Revision: 8feb5bac3279f7c7fbbdd741a70d8debd519aa00

URL: https://github.com/llvm/llvm-project/commit/8feb5bac3279f7c7fbbdd741a70d8debd519aa00
DIFF: https://github.com/llvm/llvm-project/commit/8feb5bac3279f7c7fbbdd741a70d8debd519aa00.diff

LOG: [libc++] Add benchmarks for copy algorithms (#127328)

This patch adds benchmarks for the copy family of algorithms (copy,
copy_n, copy_if, copy_backward).

Added: 
    libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
    libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
    libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
    libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp

Modified: 
    

Removed: 
    libcxx/test/benchmarks/algorithms/copy.bench.cpp
    libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp


################################################################################
diff  --git a/libcxx/test/benchmarks/algorithms/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/copy.bench.cpp
deleted file mode 100644
index b6f0f15eb7703..0000000000000
--- a/libcxx/test/benchmarks/algorithms/copy.bench.cpp
+++ /dev/null
@@ -1,89 +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, c++20
-
-#include <algorithm>
-#include <benchmark/benchmark.h>
-#include <vector>
-
-static void bm_ranges_copy_vb(benchmark::State& state, bool aligned) {
-  auto n = state.range();
-  std::vector<bool> in(n, true);
-  std::vector<bool> out(aligned ? n : n + 8);
-  benchmark::DoNotOptimize(&in);
-  auto dst = aligned ? out.begin() : out.begin() + 4;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::ranges::copy(in, dst));
-    benchmark::DoNotOptimize(&out);
-  }
-}
-
-static void bm_ranges_copy_n_vb(benchmark::State& state, bool aligned) {
-  auto n = state.range();
-  std::vector<bool> in(n, true);
-  std::vector<bool> out(aligned ? n : n + 8);
-  benchmark::DoNotOptimize(&in);
-  auto src = in.begin();
-  auto dst = aligned ? out.begin() : out.begin() + 4;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::ranges::copy_n(src, n, dst));
-    benchmark::DoNotOptimize(&out);
-  }
-}
-
-static void bm_copy_vb(benchmark::State& state, bool aligned) {
-  auto n = state.range();
-  std::vector<bool> in(n, true);
-  std::vector<bool> out(aligned ? n : n + 8);
-  benchmark::DoNotOptimize(&in);
-  auto beg = in.begin();
-  auto end = in.end();
-  auto dst = aligned ? out.begin() : out.begin() + 4;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::copy(beg, end, dst));
-    benchmark::DoNotOptimize(&out);
-  }
-}
-
-static void bm_copy_n_vb(benchmark::State& state, bool aligned) {
-  auto n = state.range();
-  std::vector<bool> in(n, true);
-  std::vector<bool> out(aligned ? n : n + 8);
-  benchmark::DoNotOptimize(&in);
-  auto src = in.begin();
-  auto dst = aligned ? out.begin() : out.begin() + 4;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::copy_n(src, n, dst));
-    benchmark::DoNotOptimize(&out);
-  }
-}
-
-static void bm_ranges_copy_vb_aligned(benchmark::State& state) { bm_ranges_copy_vb(state, true); }
-static void bm_ranges_copy_vb_unaligned(benchmark::State& state) { bm_ranges_copy_vb(state, false); }
-static void bm_ranges_copy_n_vb_aligned(benchmark::State& state) { bm_ranges_copy_n_vb(state, true); }
-static void bm_ranges_copy_n_vb_unaligned(benchmark::State& state) { bm_ranges_copy_n_vb(state, false); }
-
-static void bm_copy_vb_aligned(benchmark::State& state) { bm_copy_vb(state, true); }
-static void bm_copy_vb_unaligned(benchmark::State& state) { bm_copy_vb(state, false); }
-static void bm_copy_n_vb_aligned(benchmark::State& state) { bm_copy_n_vb(state, true); }
-static void bm_copy_n_vb_unaligned(benchmark::State& state) { bm_copy_n_vb(state, false); }
-
-// Test std::ranges::copy for vector<bool>::iterator
-BENCHMARK(bm_ranges_copy_vb_aligned)->Range(8, 1 << 16)->DenseRange(102400, 204800, 4096);
-BENCHMARK(bm_ranges_copy_n_vb_aligned)->Range(8, 1 << 20);
-BENCHMARK(bm_ranges_copy_vb_unaligned)->Range(8, 1 << 20);
-BENCHMARK(bm_ranges_copy_n_vb_unaligned)->Range(8, 1 << 20);
-
-// Test std::copy for vector<bool>::iterator
-BENCHMARK(bm_copy_vb_aligned)->Range(8, 1 << 20);
-BENCHMARK(bm_copy_n_vb_aligned)->Range(8, 1 << 20);
-BENCHMARK(bm_copy_vb_unaligned)->Range(8, 1 << 20);
-BENCHMARK(bm_copy_n_vb_unaligned)->Range(8, 1 << 20);
-
-BENCHMARK_MAIN();

diff  --git a/libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp
deleted file mode 100644
index c943d9a874b49..0000000000000
--- a/libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp
+++ /dev/null
@@ -1,55 +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, c++20
-
-#include <algorithm>
-#include <benchmark/benchmark.h>
-#include <vector>
-
-static void bm_ranges_copy_backward_vb(benchmark::State& state, bool aligned) {
-  auto n = state.range();
-  std::vector<bool> in(n, true);
-  std::vector<bool> out(aligned ? n : n + 8);
-  benchmark::DoNotOptimize(&in);
-  auto dst = aligned ? out.end() : out.end() - 4;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::ranges::copy_backward(in, dst));
-    benchmark::DoNotOptimize(&out);
-  }
-}
-
-static void bm_copy_backward_vb(benchmark::State& state, bool aligned) {
-  auto n = state.range();
-  std::vector<bool> in(n, true);
-  std::vector<bool> out(aligned ? n : n + 8);
-  benchmark::DoNotOptimize(&in);
-  auto beg = in.begin();
-  auto end = in.end();
-  auto dst = aligned ? out.end() : out.end() - 4;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::copy_backward(beg, end, dst));
-    benchmark::DoNotOptimize(&out);
-  }
-}
-
-static void bm_ranges_copy_backward_vb_aligned(benchmark::State& state) { bm_ranges_copy_backward_vb(state, true); }
-static void bm_ranges_copy_backward_vb_unaligned(benchmark::State& state) { bm_ranges_copy_backward_vb(state, false); }
-
-static void bm_copy_backward_vb_aligned(benchmark::State& state) { bm_copy_backward_vb(state, true); }
-static void bm_copy_backward_vb_unaligned(benchmark::State& state) { bm_copy_backward_vb(state, false); }
-
-// Test std::ranges::copy_backward for vector<bool>::iterator
-BENCHMARK(bm_ranges_copy_backward_vb_aligned)->Range(8, 1 << 16)->DenseRange(102400, 204800, 4096);
-BENCHMARK(bm_ranges_copy_backward_vb_unaligned)->Range(8, 1 << 20);
-
-// Test std::copy_backward for vector<bool>::iterator
-BENCHMARK(bm_copy_backward_vb_aligned)->Range(8, 1 << 20);
-BENCHMARK(bm_copy_backward_vb_unaligned)->Range(8, 1 << 20);
-
-BENCHMARK_MAIN();

diff  --git a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
new file mode 100644
index 0000000000000..3549d918478bd
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+int main(int argc, char** argv) {
+  auto std_copy = [](auto first, auto last, auto out) { return std::copy(first, last, out); };
+
+  // {std,ranges}::copy(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto copy) {
+      benchmark::RegisterBenchmark(name, [copy](auto& st) {
+        std::size_t const n = st.range(0);
+        using ValueType     = typename Container::value_type;
+        Container c;
+        std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
+
+        std::vector<ValueType> out(n);
+
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(c);
+          benchmark::DoNotOptimize(out);
+          auto result = copy(c.begin(), c.end(), out.begin());
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(8, 1 << 20);
+    };
+    bm.operator()<std::vector<int>>("std::copy(vector<int>)", std_copy);
+    bm.operator()<std::deque<int>>("std::copy(deque<int>)", std_copy);
+    bm.operator()<std::list<int>>("std::copy(list<int>)", std_copy);
+    bm.operator()<std::vector<int>>("rng::copy(vector<int>)", std::ranges::copy);
+    bm.operator()<std::deque<int>>("rng::copy(deque<int>)", std::ranges::copy);
+    bm.operator()<std::list<int>>("rng::copy(list<int>)", std::ranges::copy);
+  }
+
+  // {std,ranges}::copy(vector<bool>)
+  {
+    auto bm = []<bool Aligned>(std::string name, auto copy) {
+      benchmark::RegisterBenchmark(name, [copy](auto& st) {
+        std::size_t const n = st.range(0);
+        std::vector<bool> in(n, true);
+        std::vector<bool> out(Aligned ? n : n + 8);
+        auto first = in.begin();
+        auto last  = in.end();
+        auto dst   = Aligned ? out.begin() : out.begin() + 4;
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(in);
+          benchmark::DoNotOptimize(out);
+          auto result = copy(first, last, dst);
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(64, 1 << 20);
+    };
+    bm.operator()<true>("std::copy(vector<bool>) (aligned)", std_copy);
+    bm.operator()<false>("std::copy(vector<bool>) (unaligned)", std_copy);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+    bm.operator()<true>("rng::copy(vector<bool>) (aligned)", std::ranges::copy);
+    bm.operator()<false>("rng::copy(vector<bool>) (unaligned)", std::ranges::copy);
+#endif
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}

diff  --git a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
new file mode 100644
index 0000000000000..f97a7a84d5e0a
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
@@ -0,0 +1,84 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+int main(int argc, char** argv) {
+  auto std_copy_backward = [](auto first, auto last, auto out) { return std::copy_backward(first, last, out); };
+
+  // {std,ranges}::copy_n(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto copy_backward) {
+      benchmark::RegisterBenchmark(name, [copy_backward](auto& st) {
+        std::size_t const n = st.range(0);
+        using ValueType     = typename Container::value_type;
+        Container c;
+        std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
+
+        std::vector<ValueType> out(n);
+
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(c);
+          benchmark::DoNotOptimize(out);
+          auto result = copy_backward(c.begin(), c.end(), out.end());
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(8, 1 << 20);
+    };
+    bm.operator()<std::vector<int>>("std::copy_backward(vector<int>)", std_copy_backward);
+    bm.operator()<std::deque<int>>("std::copy_backward(deque<int>)", std_copy_backward);
+    bm.operator()<std::list<int>>("std::copy_backward(list<int>)", std_copy_backward);
+    bm.operator()<std::vector<int>>("rng::copy_backward(vector<int>)", std::ranges::copy_backward);
+    bm.operator()<std::deque<int>>("rng::copy_backward(deque<int>)", std::ranges::copy_backward);
+    bm.operator()<std::list<int>>("rng::copy_backward(list<int>)", std::ranges::copy_backward);
+  }
+
+  // {std,ranges}::copy_n(vector<bool>)
+  {
+    auto bm = []<bool Aligned>(std::string name, auto copy_backward) {
+      benchmark::RegisterBenchmark(name, [copy_backward](auto& st) {
+        std::size_t const n = st.range(0);
+        std::vector<bool> in(n, true);
+        std::vector<bool> out(Aligned ? n : n + 8);
+        benchmark::DoNotOptimize(&in);
+        auto first = in.begin();
+        auto last  = in.end();
+        auto dst   = Aligned ? out.end() : out.end() - 4;
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(in);
+          benchmark::DoNotOptimize(out);
+          auto result = copy_backward(first, last, dst);
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(64, 1 << 20);
+    };
+    bm.operator()<true>("std::copy_backward(vector<bool>) (aligned)", std_copy_backward);
+    bm.operator()<false>("std::copy_backward(vector<bool>) (unaligned)", std_copy_backward);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+    bm.operator()<true>("rng::copy_backward(vector<bool>) (aligned)", std::ranges::copy_backward);
+    bm.operator()<false>("rng::copy_backward(vector<bool>) (unaligned)", std::ranges::copy_backward);
+#endif
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}

diff  --git a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
new file mode 100644
index 0000000000000..76c653fc7f941
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
@@ -0,0 +1,98 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+int main(int argc, char** argv) {
+  auto std_copy_if = [](auto first, auto last, auto out, auto pred) { return std::copy_if(first, last, out, pred); };
+
+  // Benchmark {std,ranges}::copy_if where we copy one out of two element, in alternance.
+  // This is basically the worst case for this algorithm, I don't think there are many
+  // optimizations that can be applied in this case.
+  {
+    auto bm = []<class Container>(std::string name, auto copy_if) {
+      benchmark::RegisterBenchmark(name, [copy_if](auto& st) {
+        std::size_t const n = st.range(0);
+        using ValueType     = typename Container::value_type;
+        Container c;
+        std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
+
+        std::vector<ValueType> out(n);
+
+        for ([[maybe_unused]] auto _ : st) {
+          bool do_copy = false;
+          auto pred    = [&do_copy](auto& element) {
+            benchmark::DoNotOptimize(element);
+            do_copy = !do_copy;
+            return do_copy;
+          };
+          benchmark::DoNotOptimize(c);
+          benchmark::DoNotOptimize(out);
+          auto result = copy_if(c.begin(), c.end(), out.begin(), pred);
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(8, 1 << 20);
+    };
+    bm.operator()<std::vector<int>>("std::copy_if(vector<int>) (every other)", std_copy_if);
+    bm.operator()<std::deque<int>>("std::copy_if(deque<int>) (every other)", std_copy_if);
+    bm.operator()<std::list<int>>("std::copy_if(list<int>) (every other)", std_copy_if);
+
+    bm.operator()<std::vector<int>>("rng::copy_if(vector<int>) (every other)", std::ranges::copy_if);
+    bm.operator()<std::deque<int>>("rng::copy_if(deque<int>) (every other)", std::ranges::copy_if);
+    bm.operator()<std::list<int>>("rng::copy_if(list<int>) (every other)", std::ranges::copy_if);
+  }
+
+  // Benchmark {std,ranges}::copy_if where we copy the full range.
+  // Copy the full range.
+  {
+    auto bm = []<class Container>(std::string name, auto copy_if) {
+      benchmark::RegisterBenchmark(name, [copy_if](auto& st) {
+        std::size_t const n = st.range(0);
+        using ValueType     = typename Container::value_type;
+        Container c;
+        std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
+
+        std::vector<ValueType> out(n);
+
+        for ([[maybe_unused]] auto _ : st) {
+          auto pred = [](auto& element) {
+            benchmark::DoNotOptimize(element);
+            return true;
+          };
+          benchmark::DoNotOptimize(c);
+          benchmark::DoNotOptimize(out);
+          auto result = copy_if(c.begin(), c.end(), out.begin(), pred);
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(8, 1 << 20);
+    };
+    bm.operator()<std::vector<int>>("std::copy_if(vector<int>) (entire range)", std_copy_if);
+    bm.operator()<std::deque<int>>("std::copy_if(deque<int>) (entire range)", std_copy_if);
+    bm.operator()<std::list<int>>("std::copy_if(list<int>) (entire range)", std_copy_if);
+
+    bm.operator()<std::vector<int>>("rng::copy_if(vector<int>) (entire range)", std::ranges::copy_if);
+    bm.operator()<std::deque<int>>("rng::copy_if(deque<int>) (entire range)", std::ranges::copy_if);
+    bm.operator()<std::list<int>>("rng::copy_if(list<int>) (entire range)", std::ranges::copy_if);
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}

diff  --git a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
new file mode 100644
index 0000000000000..35d3c5c78df13
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+int main(int argc, char** argv) {
+  auto std_copy_n = [](auto first, auto n, auto out) { return std::copy_n(first, n, out); };
+
+  // {std,ranges}::copy_n(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto copy_n) {
+      benchmark::RegisterBenchmark(name, [copy_n](auto& st) {
+        std::size_t const n = st.range(0);
+        using ValueType     = typename Container::value_type;
+        Container c;
+        std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
+
+        std::vector<ValueType> out(n);
+
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(c);
+          benchmark::DoNotOptimize(out);
+          auto result = copy_n(c.begin(), n, out.begin());
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(8, 1 << 20);
+    };
+    bm.operator()<std::vector<int>>("std::copy_n(vector<int>)", std_copy_n);
+    bm.operator()<std::deque<int>>("std::copy_n(deque<int>)", std_copy_n);
+    bm.operator()<std::list<int>>("std::copy_n(list<int>)", std_copy_n);
+    bm.operator()<std::vector<int>>("rng::copy_n(vector<int>)", std::ranges::copy_n);
+    bm.operator()<std::deque<int>>("rng::copy_n(deque<int>)", std::ranges::copy_n);
+    bm.operator()<std::list<int>>("rng::copy_n(list<int>)", std::ranges::copy_n);
+  }
+
+  // {std,ranges}::copy_n(vector<bool>)
+  {
+    auto bm = []<bool Aligned>(std::string name, auto copy_n) {
+      benchmark::RegisterBenchmark(name, [copy_n](auto& st) {
+        std::size_t const n = st.range(0);
+        std::vector<bool> in(n, true);
+        std::vector<bool> out(Aligned ? n : n + 8);
+        auto first = in.begin();
+        auto dst   = Aligned ? out.begin() : out.begin() + 4;
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(in);
+          benchmark::DoNotOptimize(out);
+          auto result = copy_n(first, n, dst);
+          benchmark::DoNotOptimize(result);
+        }
+      })->Range(64, 1 << 20);
+    };
+    bm.operator()<true>("std::copy_n(vector<bool>) (aligned)", std_copy_n);
+    bm.operator()<false>("std::copy_n(vector<bool>) (unaligned)", std_copy_n);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+    bm.operator()<true>("rng::copy_n(vector<bool>) (aligned)", std::ranges::copy_n);
+    bm.operator()<false>("rng::copy_n(vector<bool>) (unaligned)", std::ranges::copy_n);
+#endif
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}


        


More information about the libcxx-commits mailing list