[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