[libcxx-commits] [libcxx] [libc++] Add benchmarks for copy algorithms (PR #127328)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Feb 19 10:46:16 PST 2025
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/127328
>From 9ae52f4845bc7489de3390c79074b5c73f85a7f6 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Sat, 15 Feb 2025 15:42:31 +0100
Subject: [PATCH 1/6] [libc++] Add benchmarks for copy algorithms
This patch adds benchmarks for the copy family of algorithms
(copy, copy_n, copy_if, copy_backward).
---
.../test/benchmarks/algorithms/copy.bench.cpp | 89 ---------------
.../algorithms/copy_backward.bench.cpp | 55 ---------
.../algorithms/modifying/copy.bench.cpp | 84 ++++++++++++++
.../modifying/copy_backward.bench.cpp | 86 ++++++++++++++
.../algorithms/modifying/copy_if.bench.cpp | 105 ++++++++++++++++++
.../algorithms/modifying/copy_n.bench.cpp | 83 ++++++++++++++
6 files changed, 358 insertions(+), 144 deletions(-)
delete mode 100644 libcxx/test/benchmarks/algorithms/copy.bench.cpp
delete mode 100644 libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/copy_n.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..dea1e9f5d7c34
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy.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 <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm_general(std::string operation_name, Operation copy) {
+ auto bench = [copy](auto& st) {
+ auto const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
+}
+
+template <bool Aligned, class Operation>
+static void bm_vector_bool(std::string operation_name, Operation copy) {
+ auto bench = [copy](auto& st) {
+ auto n = st.range();
+ 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.begin() : out.begin() + 4;
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = copy(first, last, dst);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
+}
+
+int main(int argc, char** argv) {
+ auto std_copy = [](auto first, auto last, auto out) { return std::copy(first, last, out); };
+ auto ranges_copy = [](auto first, auto last, auto out) { return std::ranges::copy(first, last, out); };
+
+ // std::copy
+ bm_general<std::vector<int>>("std::copy(vector<int>)", std_copy);
+ bm_general<std::deque<int>>("std::copy(deque<int>)", std_copy);
+ bm_general<std::list<int>>("std::copy(list<int>)", std_copy);
+ bm_vector_bool<true>("std::copy(vector<bool>) (aligned)", std_copy);
+ bm_vector_bool<false>("std::copy(vector<bool>) (unaligned)", std_copy);
+
+ // ranges::copy
+ bm_general<std::vector<int>>("ranges::copy(vector<int>)", ranges_copy);
+ bm_general<std::deque<int>>("ranges::copy(deque<int>)", ranges_copy);
+ bm_general<std::list<int>>("ranges::copy(list<int>)", ranges_copy);
+ bm_vector_bool<true>("ranges::copy(vector<bool>) (aligned)", ranges_copy);
+ bm_vector_bool<false>("ranges::copy(vector<bool>) (unaligned)", ranges_copy);
+
+ 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..6f9360533db28
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.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
+
+#include <algorithm>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm_general(std::string operation_name, Operation copy_backward) {
+ auto bench = [copy_backward](auto& st) {
+ auto const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = copy_backward(c.begin(), c.end(), out.end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
+}
+
+template <bool Aligned, class Operation>
+static void bm_vector_bool(std::string operation_name, Operation copy_backward) {
+ auto bench = [copy_backward](auto& st) {
+ auto n = st.range();
+ 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) {
+ auto result = copy_backward(first, last, dst);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
+}
+
+int main(int argc, char** argv) {
+ auto std_copy_backward = [](auto first, auto last, auto out) { return std::copy_backward(first, last, out); };
+ auto ranges_copy_backward = [](auto first, auto last, auto out) {
+ return std::ranges::copy_backward(first, last, out);
+ };
+
+ // std::copy
+ bm_general<std::vector<int>>("std::copy_backward(vector<int>)", std_copy_backward);
+ bm_general<std::deque<int>>("std::copy_backward(deque<int>)", std_copy_backward);
+ bm_general<std::list<int>>("std::copy_backward(list<int>)", std_copy_backward);
+ bm_vector_bool<true>("std::copy_backward(vector<bool>) (aligned)", std_copy_backward);
+ bm_vector_bool<false>("std::copy_backward(vector<bool>) (unaligned)", std_copy_backward);
+
+ // ranges::copy
+ bm_general<std::vector<int>>("ranges::copy_backward(vector<int>)", ranges_copy_backward);
+ bm_general<std::deque<int>>("ranges::copy_backward(deque<int>)", ranges_copy_backward);
+ bm_general<std::list<int>>("ranges::copy_backward(list<int>)", ranges_copy_backward);
+ bm_vector_bool<true>("ranges::copy_backward(vector<bool>) (aligned)", ranges_copy_backward);
+ bm_vector_bool<false>("ranges::copy_backward(vector<bool>) (unaligned)", ranges_copy_backward);
+
+ 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..8a298c703e4e8
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Benchmark copying 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.
+template <class Container, class Operation>
+void bm_copy_every_other_element(std::string operation_name, Operation copy_if) {
+ auto bench = [copy_if](auto& st) {
+ auto const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+ std::vector<ValueType> out(size);
+
+ 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;
+ };
+ auto result = copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
+}
+
+// Copy the full range.
+template <class Container, class Operation>
+void bm_copy_entire_range(std::string operation_name, Operation copy_if) {
+ auto bench = [copy_if](auto& st) {
+ auto const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto pred = [](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return true;
+ };
+ auto result = copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
+}
+
+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); };
+ auto ranges_copy_if = [](auto first, auto last, auto out, auto pred) {
+ return std::ranges::copy_if(first, last, out, pred);
+ };
+
+ // std::copy_if
+ bm_copy_every_other_element<std::vector<int>>("std::copy_if(vector<int>) (every other)", std_copy_if);
+ bm_copy_every_other_element<std::deque<int>>("std::copy_if(deque<int>) (every other)", std_copy_if);
+ bm_copy_every_other_element<std::list<int>>("std::copy_if(list<int>) (every other)", std_copy_if);
+
+ bm_copy_entire_range<std::vector<int>>("std::copy_if(vector<int>) (entire range)", std_copy_if);
+ bm_copy_entire_range<std::deque<int>>("std::copy_if(deque<int>) (entire range)", std_copy_if);
+ bm_copy_entire_range<std::list<int>>("std::copy_if(list<int>) (entire range)", std_copy_if);
+
+ // ranges::copy
+ bm_copy_every_other_element<std::vector<int>>("ranges::copy_if(vector<int>) (every other)", ranges_copy_if);
+ bm_copy_every_other_element<std::deque<int>>("ranges::copy_if(deque<int>) (every other)", ranges_copy_if);
+ bm_copy_every_other_element<std::list<int>>("ranges::copy_if(list<int>) (every other)", ranges_copy_if);
+
+ bm_copy_entire_range<std::vector<int>>("ranges::copy_if(vector<int>) (entire range)", ranges_copy_if);
+ bm_copy_entire_range<std::deque<int>>("ranges::copy_if(deque<int>) (entire range)", ranges_copy_if);
+ bm_copy_entire_range<std::list<int>>("ranges::copy_if(list<int>) (entire range)", 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..f4eb98f91df1c
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.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 <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm_general(std::string operation_name, Operation copy_n) {
+ auto bench = [copy_n](auto& st) {
+ auto const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = copy_n(c.begin(), size, out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
+}
+
+template <bool Aligned, class Operation>
+static void bm_vector_bool(std::string operation_name, Operation copy_n) {
+ auto bench = [copy_n](auto& st) {
+ auto n = st.range();
+ std::vector<bool> in(n, true);
+ std::vector<bool> out(Aligned ? n : n + 8);
+ benchmark::DoNotOptimize(&in);
+ auto first = in.begin();
+ auto dst = Aligned ? out.begin() : out.begin() + 4;
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = copy_n(first, n, dst);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
+}
+
+int main(int argc, char** argv) {
+ auto std_copy_n = [](auto first, auto n, auto out) { return std::copy_n(first, n, out); };
+ auto ranges_copy_n = [](auto first, auto n, auto out) { return std::ranges::copy_n(first, n, out); };
+
+ // std::copy_n
+ bm_general<std::vector<int>>("std::copy_n(vector<int>)", std_copy_n);
+ bm_general<std::deque<int>>("std::copy_n(deque<int>)", std_copy_n);
+ bm_general<std::list<int>>("std::copy_n(list<int>)", std_copy_n);
+ bm_vector_bool<true>("std::copy_n(vector<bool>) (aligned)", std_copy_n);
+ bm_vector_bool<false>("std::copy_n(vector<bool>) (unaligned)", std_copy_n);
+
+ // ranges::copy_n
+ bm_general<std::vector<int>>("ranges::copy_n(vector<int>)", ranges_copy_n);
+ bm_general<std::deque<int>>("ranges::copy_n(deque<int>)", ranges_copy_n);
+ bm_general<std::list<int>>("ranges::copy_n(list<int>)", ranges_copy_n);
+ bm_vector_bool<true>("ranges::copy_n(vector<bool>) (aligned)", ranges_copy_n);
+ bm_vector_bool<false>("ranges::copy_n(vector<bool>) (unaligned)", ranges_copy_n);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
>From 76b025a1f79c71b1af5462bc7a0bdee094af8c4b Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Sun, 16 Feb 2025 00:49:16 +0100
Subject: [PATCH 2/6] Guard for lack of output_iterator-nesss
---
libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp | 3 +++
.../benchmarks/algorithms/modifying/copy_backward.bench.cpp | 3 +++
libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp | 3 +++
3 files changed, 9 insertions(+)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
index dea1e9f5d7c34..a3db7dce1bde5 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
@@ -17,6 +17,7 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
+#include "test_macros.h"
template <class Container, class Operation>
void bm_general(std::string operation_name, Operation copy) {
@@ -74,8 +75,10 @@ int main(int argc, char** argv) {
bm_general<std::vector<int>>("ranges::copy(vector<int>)", ranges_copy);
bm_general<std::deque<int>>("ranges::copy(deque<int>)", ranges_copy);
bm_general<std::list<int>>("ranges::copy(list<int>)", ranges_copy);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
bm_vector_bool<true>("ranges::copy(vector<bool>) (aligned)", ranges_copy);
bm_vector_bool<false>("ranges::copy(vector<bool>) (unaligned)", ranges_copy);
+#endif
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
index 6f9360533db28..b9adb24ad5964 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
@@ -17,6 +17,7 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
+#include "test_macros.h"
template <class Container, class Operation>
void bm_general(std::string operation_name, Operation copy_backward) {
@@ -76,8 +77,10 @@ int main(int argc, char** argv) {
bm_general<std::vector<int>>("ranges::copy_backward(vector<int>)", ranges_copy_backward);
bm_general<std::deque<int>>("ranges::copy_backward(deque<int>)", ranges_copy_backward);
bm_general<std::list<int>>("ranges::copy_backward(list<int>)", ranges_copy_backward);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
bm_vector_bool<true>("ranges::copy_backward(vector<bool>) (aligned)", ranges_copy_backward);
bm_vector_bool<false>("ranges::copy_backward(vector<bool>) (unaligned)", ranges_copy_backward);
+#endif
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
index f4eb98f91df1c..c95dd327fc01c 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
@@ -17,6 +17,7 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
+#include "test_macros.h"
template <class Container, class Operation>
void bm_general(std::string operation_name, Operation copy_n) {
@@ -73,8 +74,10 @@ int main(int argc, char** argv) {
bm_general<std::vector<int>>("ranges::copy_n(vector<int>)", ranges_copy_n);
bm_general<std::deque<int>>("ranges::copy_n(deque<int>)", ranges_copy_n);
bm_general<std::list<int>>("ranges::copy_n(list<int>)", ranges_copy_n);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
bm_vector_bool<true>("ranges::copy_n(vector<bool>) (aligned)", ranges_copy_n);
bm_vector_bool<false>("ranges::copy_n(vector<bool>) (unaligned)", ranges_copy_n);
+#endif
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
>From b2122045f0e2d04a09471ca985fb31514155335f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 18 Feb 2025 15:30:42 -0500
Subject: [PATCH 3/6] Use ranges CPOs directly
---
libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp | 2 +-
.../benchmarks/algorithms/modifying/copy_backward.bench.cpp | 4 +---
libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp | 4 +---
libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp | 2 +-
4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
index a3db7dce1bde5..3daebcc0240f6 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
@@ -62,7 +62,7 @@ static void bm_vector_bool(std::string operation_name, Operation copy) {
int main(int argc, char** argv) {
auto std_copy = [](auto first, auto last, auto out) { return std::copy(first, last, out); };
- auto ranges_copy = [](auto first, auto last, auto out) { return std::ranges::copy(first, last, out); };
+ auto ranges_copy = std::ranges::copy;
// std::copy
bm_general<std::vector<int>>("std::copy(vector<int>)", std_copy);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
index b9adb24ad5964..ca5ea7fd279bd 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
@@ -62,9 +62,7 @@ static void bm_vector_bool(std::string operation_name, Operation copy_backward)
int main(int argc, char** argv) {
auto std_copy_backward = [](auto first, auto last, auto out) { return std::copy_backward(first, last, out); };
- auto ranges_copy_backward = [](auto first, auto last, auto out) {
- return std::ranges::copy_backward(first, last, out);
- };
+ auto ranges_copy_backward = std::ranges::copy_backward;
// std::copy
bm_general<std::vector<int>>("std::copy_backward(vector<int>)", std_copy_backward);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
index 8a298c703e4e8..e9cb9ab08ce1a 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
@@ -76,9 +76,7 @@ void bm_copy_entire_range(std::string operation_name, Operation copy_if) {
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); };
- auto ranges_copy_if = [](auto first, auto last, auto out, auto pred) {
- return std::ranges::copy_if(first, last, out, pred);
- };
+ auto ranges_copy_if = std::ranges::copy_if;
// std::copy_if
bm_copy_every_other_element<std::vector<int>>("std::copy_if(vector<int>) (every other)", std_copy_if);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
index c95dd327fc01c..7a047c86369ab 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
@@ -61,7 +61,7 @@ static void bm_vector_bool(std::string operation_name, Operation copy_n) {
int main(int argc, char** argv) {
auto std_copy_n = [](auto first, auto n, auto out) { return std::copy_n(first, n, out); };
- auto ranges_copy_n = [](auto first, auto n, auto out) { return std::ranges::copy_n(first, n, out); };
+ auto ranges_copy_n = std::ranges::copy_n;
// std::copy_n
bm_general<std::vector<int>>("std::copy_n(vector<int>)", std_copy_n);
>From d672c6dc52a1c2e15ac34ff5d617f95211bdf2f9 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 09:36:11 -0500
Subject: [PATCH 4/6] Fix uses of ClobberMemory
---
.../algorithms/modifying/copy.bench.cpp | 21 +++++++--------
.../modifying/copy_backward.bench.cpp | 20 +++++++-------
.../algorithms/modifying/copy_if.bench.cpp | 27 +++++++++----------
.../algorithms/modifying/copy_n.bench.cpp | 23 ++++++++--------
4 files changed, 44 insertions(+), 47 deletions(-)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
index 3daebcc0240f6..2ec09c3c0d056 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
@@ -9,6 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
#include <algorithm>
+#include <cstddef>
#include <deque>
#include <iterator>
#include <list>
@@ -22,19 +23,18 @@
template <class Container, class Operation>
void bm_general(std::string operation_name, Operation copy) {
auto bench = [copy](auto& st) {
- auto const size = st.range(0);
- using ValueType = typename Container::value_type;
+ std::size_t const n = st.range(0);
+ using ValueType = typename Container::value_type;
Container c;
- std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
- std::vector<ValueType> out(size);
+ 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);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
@@ -43,18 +43,17 @@ void bm_general(std::string operation_name, Operation copy) {
template <bool Aligned, class Operation>
static void bm_vector_bool(std::string operation_name, Operation copy) {
auto bench = [copy](auto& st) {
- auto n = st.range();
+ 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.begin() : out.begin() + 4;
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(in);
+ benchmark::DoNotOptimize(out);
auto result = copy(first, last, dst);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(out);
- benchmark::ClobberMemory();
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
index ca5ea7fd279bd..42265c9e9cd2d 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
@@ -9,6 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
#include <algorithm>
+#include <cstddef>
#include <deque>
#include <iterator>
#include <list>
@@ -22,19 +23,18 @@
template <class Container, class Operation>
void bm_general(std::string operation_name, Operation copy_backward) {
auto bench = [copy_backward](auto& st) {
- auto const size = st.range(0);
- using ValueType = typename Container::value_type;
+ std::size_t const n = st.range(0);
+ using ValueType = typename Container::value_type;
Container c;
- std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
- std::vector<ValueType> out(size);
+ 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);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
@@ -43,7 +43,7 @@ void bm_general(std::string operation_name, Operation copy_backward) {
template <bool Aligned, class Operation>
static void bm_vector_bool(std::string operation_name, Operation copy_backward) {
auto bench = [copy_backward](auto& st) {
- auto n = st.range();
+ 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);
@@ -51,10 +51,10 @@ static void bm_vector_bool(std::string operation_name, Operation copy_backward)
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);
- benchmark::DoNotOptimize(out);
- benchmark::ClobberMemory();
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
index e9cb9ab08ce1a..ac9e42d2d2235 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
@@ -9,6 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
#include <algorithm>
+#include <cstddef>
#include <deque>
#include <iterator>
#include <list>
@@ -24,12 +25,12 @@
template <class Container, class Operation>
void bm_copy_every_other_element(std::string operation_name, Operation copy_if) {
auto bench = [copy_if](auto& st) {
- auto const size = st.range(0);
- using ValueType = typename Container::value_type;
+ std::size_t const n = st.range(0);
+ using ValueType = typename Container::value_type;
Container c;
- std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
- std::vector<ValueType> out(size);
+ std::vector<ValueType> out(n);
for ([[maybe_unused]] auto _ : st) {
bool do_copy = false;
@@ -38,11 +39,10 @@ void bm_copy_every_other_element(std::string operation_name, Operation copy_if)
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);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
@@ -52,23 +52,22 @@ void bm_copy_every_other_element(std::string operation_name, Operation copy_if)
template <class Container, class Operation>
void bm_copy_entire_range(std::string operation_name, Operation copy_if) {
auto bench = [copy_if](auto& st) {
- auto const size = st.range(0);
- using ValueType = typename Container::value_type;
+ std::size_t const n = st.range(0);
+ using ValueType = typename Container::value_type;
Container c;
- std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
- std::vector<ValueType> out(size);
+ 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);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
index 7a047c86369ab..ad70b9fb3c7e7 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
@@ -9,6 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
#include <algorithm>
+#include <cstddef>
#include <deque>
#include <iterator>
#include <list>
@@ -22,19 +23,18 @@
template <class Container, class Operation>
void bm_general(std::string operation_name, Operation copy_n) {
auto bench = [copy_n](auto& st) {
- auto const size = st.range(0);
- using ValueType = typename Container::value_type;
+ std::size_t const n = st.range(0);
+ using ValueType = typename Container::value_type;
Container c;
- std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
- std::vector<ValueType> out(size);
+ std::vector<ValueType> out(n);
for ([[maybe_unused]] auto _ : st) {
- auto result = copy_n(c.begin(), size, out.begin());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(out);
benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
+ benchmark::DoNotOptimize(out);
+ auto result = copy_n(c.begin(), n, out.begin());
+ benchmark::DoNotOptimize(result);
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
@@ -43,17 +43,16 @@ void bm_general(std::string operation_name, Operation copy_n) {
template <bool Aligned, class Operation>
static void bm_vector_bool(std::string operation_name, Operation copy_n) {
auto bench = [copy_n](auto& st) {
- auto n = st.range();
+ 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 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);
- benchmark::DoNotOptimize(out);
- benchmark::ClobberMemory();
}
};
benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
>From d34de3e0f1c4f8ca40d95e9d8508db64b55d7618 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 10:18:47 -0500
Subject: [PATCH 5/6] Implement consensus with Nikolas
---
.../algorithms/modifying/copy.bench.cpp | 101 +++++++-------
.../modifying/copy_backward.bench.cpp | 103 +++++++-------
.../algorithms/modifying/copy_if.bench.cpp | 130 +++++++++---------
.../algorithms/modifying/copy_n.bench.cpp | 99 +++++++------
4 files changed, 210 insertions(+), 223 deletions(-)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
index 2ec09c3c0d056..5c29260f9da37 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
@@ -20,64 +20,61 @@
#include "../../GenerateInput.h"
#include "test_macros.h"
-template <class Container, class Operation>
-void bm_general(std::string operation_name, Operation copy) {
- auto bench = [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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
-}
+int main(int argc, char** argv) {
+ auto std_copy = [](auto first, auto last, auto out) { return std::copy(first, last, out); };
-template <bool Aligned, class Operation>
-static void bm_vector_bool(std::string operation_name, Operation copy) {
- auto bench = [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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
-}
+ // {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(); });
-int main(int argc, char** argv) {
- auto std_copy = [](auto first, auto last, auto out) { return std::copy(first, last, out); };
- auto ranges_copy = std::ranges::copy;
+ std::vector<ValueType> out(n);
- // std::copy
- bm_general<std::vector<int>>("std::copy(vector<int>)", std_copy);
- bm_general<std::deque<int>>("std::copy(deque<int>)", std_copy);
- bm_general<std::list<int>>("std::copy(list<int>)", std_copy);
- bm_vector_bool<true>("std::copy(vector<bool>) (aligned)", std_copy);
- bm_vector_bool<false>("std::copy(vector<bool>) (unaligned)", std_copy);
+ 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>>("ranges::copy(vector<int>)", std::ranges::copy);
+ bm.operator()<std::deque<int>>("ranges::copy(deque<int>)", std::ranges::copy);
+ bm.operator()<std::list<int>>("ranges::copy(list<int>)", std::ranges::copy);
+ }
- // ranges::copy
- bm_general<std::vector<int>>("ranges::copy(vector<int>)", ranges_copy);
- bm_general<std::deque<int>>("ranges::copy(deque<int>)", ranges_copy);
- bm_general<std::list<int>>("ranges::copy(list<int>)", 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_vector_bool<true>("ranges::copy(vector<bool>) (aligned)", ranges_copy);
- bm_vector_bool<false>("ranges::copy(vector<bool>) (unaligned)", ranges_copy);
+ bm.operator()<true>("ranges::copy(vector<bool>) (aligned)", std::ranges::copy);
+ bm.operator()<false>("ranges::copy(vector<bool>) (unaligned)", std::ranges::copy);
#endif
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
index 42265c9e9cd2d..15122652f28ae 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
@@ -20,65 +20,62 @@
#include "../../GenerateInput.h"
#include "test_macros.h"
-template <class Container, class Operation>
-void bm_general(std::string operation_name, Operation copy_backward) {
- auto bench = [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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
-}
+int main(int argc, char** argv) {
+ auto std_copy_backward = [](auto first, auto last, auto out) { return std::copy_backward(first, last, out); };
-template <bool Aligned, class Operation>
-static void bm_vector_bool(std::string operation_name, Operation copy_backward) {
- auto bench = [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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
-}
+ // {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(); });
-int main(int argc, char** argv) {
- auto std_copy_backward = [](auto first, auto last, auto out) { return std::copy_backward(first, last, out); };
- auto ranges_copy_backward = std::ranges::copy_backward;
+ std::vector<ValueType> out(n);
- // std::copy
- bm_general<std::vector<int>>("std::copy_backward(vector<int>)", std_copy_backward);
- bm_general<std::deque<int>>("std::copy_backward(deque<int>)", std_copy_backward);
- bm_general<std::list<int>>("std::copy_backward(list<int>)", std_copy_backward);
- bm_vector_bool<true>("std::copy_backward(vector<bool>) (aligned)", std_copy_backward);
- bm_vector_bool<false>("std::copy_backward(vector<bool>) (unaligned)", std_copy_backward);
+ 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>>("ranges::copy_backward(vector<int>)", std::ranges::copy_backward);
+ bm.operator()<std::deque<int>>("ranges::copy_backward(deque<int>)", std::ranges::copy_backward);
+ bm.operator()<std::list<int>>("ranges::copy_backward(list<int>)", std::ranges::copy_backward);
+ }
- // ranges::copy
- bm_general<std::vector<int>>("ranges::copy_backward(vector<int>)", ranges_copy_backward);
- bm_general<std::deque<int>>("ranges::copy_backward(deque<int>)", ranges_copy_backward);
- bm_general<std::list<int>>("ranges::copy_backward(list<int>)", 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_vector_bool<true>("ranges::copy_backward(vector<bool>) (aligned)", ranges_copy_backward);
- bm_vector_bool<false>("ranges::copy_backward(vector<bool>) (unaligned)", ranges_copy_backward);
+ bm.operator()<true>("ranges::copy_backward(vector<bool>) (aligned)", std::ranges::copy_backward);
+ bm.operator()<false>("ranges::copy_backward(vector<bool>) (unaligned)", std::ranges::copy_backward);
#endif
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
index ac9e42d2d2235..ab6889de52296 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
@@ -19,81 +19,77 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Benchmark copying 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.
-template <class Container, class Operation>
-void bm_copy_every_other_element(std::string operation_name, Operation copy_if) {
- auto bench = [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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
-}
+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); };
-// Copy the full range.
-template <class Container, class Operation>
-void bm_copy_entire_range(std::string operation_name, Operation copy_if) {
- auto bench = [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(); });
+ // 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);
+ 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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
-}
+ 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);
-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); };
- auto ranges_copy_if = std::ranges::copy_if;
+ bm.operator()<std::vector<int>>("ranges::copy_if(vector<int>) (every other)", std::ranges::copy_if);
+ bm.operator()<std::deque<int>>("ranges::copy_if(deque<int>) (every other)", std::ranges::copy_if);
+ bm.operator()<std::list<int>>("ranges::copy_if(list<int>) (every other)", std::ranges::copy_if);
+ }
- // std::copy_if
- bm_copy_every_other_element<std::vector<int>>("std::copy_if(vector<int>) (every other)", std_copy_if);
- bm_copy_every_other_element<std::deque<int>>("std::copy_if(deque<int>) (every other)", std_copy_if);
- bm_copy_every_other_element<std::list<int>>("std::copy_if(list<int>) (every other)", std_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(); });
- bm_copy_entire_range<std::vector<int>>("std::copy_if(vector<int>) (entire range)", std_copy_if);
- bm_copy_entire_range<std::deque<int>>("std::copy_if(deque<int>) (entire range)", std_copy_if);
- bm_copy_entire_range<std::list<int>>("std::copy_if(list<int>) (entire range)", std_copy_if);
+ std::vector<ValueType> out(n);
- // ranges::copy
- bm_copy_every_other_element<std::vector<int>>("ranges::copy_if(vector<int>) (every other)", ranges_copy_if);
- bm_copy_every_other_element<std::deque<int>>("ranges::copy_if(deque<int>) (every other)", ranges_copy_if);
- bm_copy_every_other_element<std::list<int>>("ranges::copy_if(list<int>) (every other)", ranges_copy_if);
+ 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_copy_entire_range<std::vector<int>>("ranges::copy_if(vector<int>) (entire range)", ranges_copy_if);
- bm_copy_entire_range<std::deque<int>>("ranges::copy_if(deque<int>) (entire range)", ranges_copy_if);
- bm_copy_entire_range<std::list<int>>("ranges::copy_if(list<int>) (entire range)", ranges_copy_if);
+ bm.operator()<std::vector<int>>("ranges::copy_if(vector<int>) (entire range)", std::ranges::copy_if);
+ bm.operator()<std::deque<int>>("ranges::copy_if(deque<int>) (entire range)", std::ranges::copy_if);
+ bm.operator()<std::list<int>>("ranges::copy_if(list<int>) (entire range)", std::ranges::copy_if);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
index ad70b9fb3c7e7..539308cbbf3e1 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
@@ -20,63 +20,60 @@
#include "../../GenerateInput.h"
#include "test_macros.h"
-template <class Container, class Operation>
-void bm_general(std::string operation_name, Operation copy_n) {
- auto bench = [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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 20);
-}
+int main(int argc, char** argv) {
+ auto std_copy_n = [](auto first, auto n, auto out) { return std::copy_n(first, n, out); };
-template <bool Aligned, class Operation>
-static void bm_vector_bool(std::string operation_name, Operation copy_n) {
- auto bench = [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);
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(64, 1 << 20);
-}
+ // {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(); });
-int main(int argc, char** argv) {
- auto std_copy_n = [](auto first, auto n, auto out) { return std::copy_n(first, n, out); };
- auto ranges_copy_n = std::ranges::copy_n;
+ std::vector<ValueType> out(n);
- // std::copy_n
- bm_general<std::vector<int>>("std::copy_n(vector<int>)", std_copy_n);
- bm_general<std::deque<int>>("std::copy_n(deque<int>)", std_copy_n);
- bm_general<std::list<int>>("std::copy_n(list<int>)", std_copy_n);
- bm_vector_bool<true>("std::copy_n(vector<bool>) (aligned)", std_copy_n);
- bm_vector_bool<false>("std::copy_n(vector<bool>) (unaligned)", std_copy_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>>("ranges::copy_n(vector<int>)", std::ranges::copy_n);
+ bm.operator()<std::deque<int>>("ranges::copy_n(deque<int>)", std::ranges::copy_n);
+ bm.operator()<std::list<int>>("ranges::copy_n(list<int>)", std::ranges::copy_n);
+ }
- // ranges::copy_n
- bm_general<std::vector<int>>("ranges::copy_n(vector<int>)", ranges_copy_n);
- bm_general<std::deque<int>>("ranges::copy_n(deque<int>)", ranges_copy_n);
- bm_general<std::list<int>>("ranges::copy_n(list<int>)", 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_vector_bool<true>("ranges::copy_n(vector<bool>) (aligned)", ranges_copy_n);
- bm_vector_bool<false>("ranges::copy_n(vector<bool>) (unaligned)", ranges_copy_n);
+ bm.operator()<true>("ranges::copy_n(vector<bool>) (aligned)", std::ranges::copy_n);
+ bm.operator()<false>("ranges::copy_n(vector<bool>) (unaligned)", std::ranges::copy_n);
#endif
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
>From bf612506961952dc1daa405eaa2f0b19a6ca242f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 13:45:45 -0500
Subject: [PATCH 6/6] Use rng::copy instead of ranges::copy -- that way the
results align better with std:: in the tabular output
---
.../benchmarks/algorithms/modifying/copy.bench.cpp | 10 +++++-----
.../algorithms/modifying/copy_backward.bench.cpp | 10 +++++-----
.../algorithms/modifying/copy_if.bench.cpp | 12 ++++++------
.../benchmarks/algorithms/modifying/copy_n.bench.cpp | 10 +++++-----
4 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
index 5c29260f9da37..3549d918478bd 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp
@@ -45,9 +45,9 @@ int main(int argc, char** argv) {
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>>("ranges::copy(vector<int>)", std::ranges::copy);
- bm.operator()<std::deque<int>>("ranges::copy(deque<int>)", std::ranges::copy);
- bm.operator()<std::list<int>>("ranges::copy(list<int>)", std::ranges::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>)
@@ -71,8 +71,8 @@ int main(int argc, char** argv) {
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>("ranges::copy(vector<bool>) (aligned)", std::ranges::copy);
- bm.operator()<false>("ranges::copy(vector<bool>) (unaligned)", std::ranges::copy);
+ bm.operator()<true>("rng::copy(vector<bool>) (aligned)", std::ranges::copy);
+ bm.operator()<false>("rng::copy(vector<bool>) (unaligned)", std::ranges::copy);
#endif
}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
index 15122652f28ae..f97a7a84d5e0a 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp
@@ -45,9 +45,9 @@ int main(int argc, char** argv) {
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>>("ranges::copy_backward(vector<int>)", std::ranges::copy_backward);
- bm.operator()<std::deque<int>>("ranges::copy_backward(deque<int>)", std::ranges::copy_backward);
- bm.operator()<std::list<int>>("ranges::copy_backward(list<int>)", std::ranges::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>)
@@ -72,8 +72,8 @@ int main(int argc, char** argv) {
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>("ranges::copy_backward(vector<bool>) (aligned)", std::ranges::copy_backward);
- bm.operator()<false>("ranges::copy_backward(vector<bool>) (unaligned)", std::ranges::copy_backward);
+ 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
}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
index ab6889de52296..76c653fc7f941 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp
@@ -53,9 +53,9 @@ int main(int argc, char** argv) {
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>>("ranges::copy_if(vector<int>) (every other)", std::ranges::copy_if);
- bm.operator()<std::deque<int>>("ranges::copy_if(deque<int>) (every other)", std::ranges::copy_if);
- bm.operator()<std::list<int>>("ranges::copy_if(list<int>) (every other)", std::ranges::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.
@@ -86,9 +86,9 @@ int main(int argc, char** argv) {
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>>("ranges::copy_if(vector<int>) (entire range)", std::ranges::copy_if);
- bm.operator()<std::deque<int>>("ranges::copy_if(deque<int>) (entire range)", std::ranges::copy_if);
- bm.operator()<std::list<int>>("ranges::copy_if(list<int>) (entire range)", std::ranges::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);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
index 539308cbbf3e1..35d3c5c78df13 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp
@@ -45,9 +45,9 @@ int main(int argc, char** argv) {
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>>("ranges::copy_n(vector<int>)", std::ranges::copy_n);
- bm.operator()<std::deque<int>>("ranges::copy_n(deque<int>)", std::ranges::copy_n);
- bm.operator()<std::list<int>>("ranges::copy_n(list<int>)", std::ranges::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>)
@@ -70,8 +70,8 @@ int main(int argc, char** argv) {
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>("ranges::copy_n(vector<bool>) (aligned)", std::ranges::copy_n);
- bm.operator()<false>("ranges::copy_n(vector<bool>) (unaligned)", std::ranges::copy_n);
+ 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
}
More information about the libcxx-commits
mailing list