[libcxx-commits] [libcxx] [libc++] Add remaining benchmarks from [alg.modifying.operations] (PR #127354)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Feb 19 13:37:14 PST 2025
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/127354
>From 232a73aec14b81590453ddcc97fd108938251f75 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Sat, 15 Feb 2025 21:36:38 +0100
Subject: [PATCH 1/4] [libc++] Add remaining benchmarks from
[alg.modifying.operations]
This patch adds benchmarks for all the remaining algorithms in
[alg.modifying.operations] that we didn't already have a benchmark
for.
---
libcxx/include/module.modulemap | 3 +-
.../test/benchmarks/algorithms/fill.bench.cpp | 51 -------
.../algorithms/modifying/fill.bench.cpp | 86 +++++++++++
.../algorithms/modifying/fill_n.bench.cpp | 86 +++++++++++
.../algorithms/modifying/generate.bench.cpp | 59 +++++++
.../algorithms/modifying/generate_n.bench.cpp | 59 +++++++
.../algorithms/modifying/remove.bench.cpp | 133 ++++++++++++++++
.../modifying/remove_copy.bench.cpp | 109 +++++++++++++
.../modifying/remove_copy_if.bench.cpp | 119 +++++++++++++++
.../algorithms/modifying/remove_if.bench.cpp | 143 +++++++++++++++++
.../algorithms/modifying/replace.bench.cpp | 107 +++++++++++++
.../algorithms/modifying/replace_if.bench.cpp | 117 ++++++++++++++
.../algorithms/modifying/reverse.bench.cpp | 57 +++++++
.../modifying/reverse_copy.bench.cpp | 61 ++++++++
.../algorithms/modifying/rotate.bench.cpp | 59 +++++++
.../modifying/rotate_copy.bench.cpp | 65 ++++++++
.../algorithms/modifying/sample.bench.cpp | 68 +++++++++
.../algorithms/modifying/shift_left.bench.cpp | 56 +++++++
.../modifying/shift_right.bench.cpp | 56 +++++++
.../algorithms/modifying/shuffle.bench.cpp | 56 +++++++
.../modifying/swap_ranges.bench.cpp | 64 ++++++++
.../modifying/transform.binary.bench.cpp | 73 +++++++++
.../modifying/transform.unary.bench.cpp | 68 +++++++++
.../algorithms/modifying/unique.bench.cpp | 132 ++++++++++++++++
.../modifying/unique_copy.bench.cpp | 105 +++++++++++++
.../modifying/unique_copy_pred.bench.cpp | 121 +++++++++++++++
.../modifying/unique_pred.bench.cpp | 144 ++++++++++++++++++
.../benchmarks/algorithms/reverse.bench.cpp | 48 ------
28 files changed, 2205 insertions(+), 100 deletions(-)
delete mode 100644 libcxx/test/benchmarks/algorithms/fill.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
delete mode 100644 libcxx/test/benchmarks/algorithms/reverse.bench.cpp
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index b0720703bd0de..6af6e96af7d75 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -700,6 +700,7 @@ module std [system] {
}
module ranges_remove {
header "__algorithm/ranges_remove.h"
+ export std.ranges.subrange // return type
}
module ranges_replace_copy_if {
header "__algorithm/ranges_replace_copy_if.h"
@@ -724,7 +725,7 @@ module std [system] {
}
module ranges_rotate_copy {
header "__algorithm/ranges_rotate_copy.h"
- export std.algorithm.in_out_result
+ export std.ranges.subrange // return type
}
module ranges_rotate { header "__algorithm/ranges_rotate.h" }
module ranges_sample { header "__algorithm/ranges_sample.h" }
diff --git a/libcxx/test/benchmarks/algorithms/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/fill.bench.cpp
deleted file mode 100644
index 6a48b25b7eb63..0000000000000
--- a/libcxx/test/benchmarks/algorithms/fill.bench.cpp
+++ /dev/null
@@ -1,51 +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_fill_n_vector_bool(benchmark::State& state) {
- std::vector<bool> vec1(state.range());
- for (auto _ : state) {
- benchmark::DoNotOptimize(vec1);
- benchmark::DoNotOptimize(std::fill_n(vec1.begin(), vec1.size(), false));
- }
-}
-BENCHMARK(bm_fill_n_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_ranges_fill_n_vector_bool(benchmark::State& state) {
- std::vector<bool> vec1(state.range());
- for (auto _ : state) {
- benchmark::DoNotOptimize(vec1);
- benchmark::DoNotOptimize(std::ranges::fill_n(vec1.begin(), vec1.size(), false));
- }
-}
-BENCHMARK(bm_ranges_fill_n_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_fill_vector_bool(benchmark::State& state) {
- std::vector<bool> vec1(state.range());
- for (auto _ : state) {
- benchmark::DoNotOptimize(vec1);
- std::fill(vec1.begin(), vec1.end(), false);
- }
-}
-BENCHMARK(bm_fill_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_ranges_fill_vector_bool(benchmark::State& state) {
- std::vector<bool> vec1(state.range());
- for (auto _ : state) {
- benchmark::DoNotOptimize(vec1);
- benchmark::DoNotOptimize(std::ranges::fill(vec1, false));
- }
-}
-BENCHMARK(bm_ranges_fill_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
new file mode 100644
index 0000000000000..64c7364be6549
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.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 <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation fill) {
+ auto bench = [fill](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ Container c(size, y);
+
+ for ([[maybe_unused]] auto _ : st) {
+ fill(c.begin(), c.end(), x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+template <class Operation>
+void bm_vector_bool(std::string operation_name, Operation fill) {
+ auto bench = [fill](auto& st) {
+ std::size_t const size = st.range(0);
+ bool x = true;
+ bool y = false;
+ std::vector<bool> c(size, y);
+
+ for ([[maybe_unused]] auto _ : st) {
+ fill(c.begin(), c.end(), x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_fill = [](auto first, auto last, auto const& value) { return std::fill(first, last, value); };
+ auto ranges_fill = [](auto first, auto last, auto const& value) { return std::ranges::fill(first, last, value); };
+
+ // std::fill
+ bm<std::vector<int>>("std::fill(vector<int>)", std_fill);
+ bm<std::deque<int>>("std::fill(deque<int>)", std_fill);
+ bm<std::list<int>>("std::fill(list<int>)", std_fill);
+ bm_vector_bool("std::fill(vector<bool>)", std_fill);
+
+ // ranges::fill
+ bm<std::vector<int>>("ranges::fill(vector<int>)", ranges_fill);
+ bm<std::deque<int>>("ranges::fill(deque<int>)", ranges_fill);
+ bm<std::list<int>>("ranges::fill(list<int>)", ranges_fill);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+ bm_vector_bool("ranges::fill(vector<bool>)", ranges_fill);
+#endif
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
new file mode 100644
index 0000000000000..aaeb0982956f9
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.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 <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation fill_n) {
+ auto bench = [fill_n](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ Container c(size, y);
+
+ for ([[maybe_unused]] auto _ : st) {
+ fill_n(c.begin(), size, x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+template <class Operation>
+void bm_vector_bool(std::string operation_name, Operation fill_n) {
+ auto bench = [fill_n](auto& st) {
+ std::size_t const size = st.range(0);
+ bool x = true;
+ bool y = false;
+ std::vector<bool> c(size, y);
+
+ for ([[maybe_unused]] auto _ : st) {
+ fill_n(c.begin(), size, x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_fill_n = [](auto out, auto n, auto const& value) { return std::fill_n(out, n, value); };
+ auto ranges_fill_n = [](auto out, auto n, auto const& value) { return std::ranges::fill_n(out, n, value); };
+
+ // std::fill_n
+ bm<std::vector<int>>("std::fill_n(vector<int>)", std_fill_n);
+ bm<std::deque<int>>("std::fill_n(deque<int>)", std_fill_n);
+ bm<std::list<int>>("std::fill_n(list<int>)", std_fill_n);
+ bm_vector_bool("std::fill_n(vector<bool>)", std_fill_n);
+
+ // ranges::fill_n
+ bm<std::vector<int>>("ranges::fill_n(vector<int>)", ranges_fill_n);
+ bm<std::deque<int>>("ranges::fill_n(deque<int>)", ranges_fill_n);
+ bm<std::list<int>>("ranges::fill_n(list<int>)", ranges_fill_n);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+ bm_vector_bool("ranges::fill_n(vector<bool>)", ranges_fill_n);
+#endif
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
new file mode 100644
index 0000000000000..15b039a4d3009
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation generate) {
+ auto bench = [generate](auto& st) {
+ std::size_t const size = st.range(0);
+ Container c(size);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto f = [&x] { return x; };
+ generate(c.begin(), c.end(), f);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_generate = [](auto first, auto last, auto f) { return std::generate(first, last, f); };
+ auto ranges_generate = [](auto first, auto last, auto f) { return std::ranges::generate(first, last, f); };
+
+ // std::generate
+ bm<std::vector<int>>("std::generate(vector<int>)", std_generate);
+ bm<std::deque<int>>("std::generate(deque<int>)", std_generate);
+ bm<std::list<int>>("std::generate(list<int>)", std_generate);
+
+ // ranges::generate
+ bm<std::vector<int>>("ranges::generate(vector<int>)", ranges_generate);
+ bm<std::deque<int>>("ranges::generate(deque<int>)", ranges_generate);
+ bm<std::list<int>>("ranges::generate(list<int>)", ranges_generate);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
new file mode 100644
index 0000000000000..75b088411810f
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation generate_n) {
+ auto bench = [generate_n](auto& st) {
+ std::size_t const size = st.range(0);
+ Container c(size);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto f = [&x] { return x; };
+ generate_n(c.begin(), size, f);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_generate_n = [](auto out, auto n, auto f) { return std::generate_n(out, n, f); };
+ auto ranges_generate_n = [](auto out, auto n, auto f) { return std::ranges::generate_n(out, n, f); };
+
+ // std::generate_n
+ bm<std::vector<int>>("std::generate_n(vector<int>)", std_generate_n);
+ bm<std::deque<int>>("std::generate_n(deque<int>)", std_generate_n);
+ bm<std::list<int>>("std::generate_n(list<int>)", std_generate_n);
+
+ // ranges::generate_n
+ bm<std::vector<int>>("ranges::generate_n(vector<int>)", ranges_generate_n);
+ bm<std::deque<int>>("ranges::generate_n(deque<int>)", ranges_generate_n);
+ bm<std::list<int>>("ranges::generate_n(list<int>)", ranges_generate_n);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
new file mode 100644
index 0000000000000..764dfe73ab70c
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -0,0 +1,133 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove) {
+ auto bench = [remove](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove(c[i].begin(), c[i].end(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove) {
+ auto bench = [remove](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; ++i) {
+ *out++ = (i % 2 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove(c[i].begin(), c[i].end(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_remove = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
+ auto ranges_remove = [](auto first, auto last, auto const& value) { return std::ranges::remove(first, last, value); };
+
+ // std::remove
+ bm_prefix<std::vector<int>>("std::remove(vector<int>) (prefix)", std_remove);
+ bm_sprinkled<std::vector<int>>("std::remove(vector<int>) (sprinkled)", std_remove);
+
+ bm_prefix<std::deque<int>>("std::remove(deque<int>) (prefix)", std_remove);
+ bm_sprinkled<std::deque<int>>("std::remove(deque<int>) (sprinkled)", std_remove);
+
+ bm_prefix<std::list<int>>("std::remove(list<int>) (prefix)", std_remove);
+ bm_sprinkled<std::list<int>>("std::remove(list<int>) (sprinkled)", std_remove);
+
+ // ranges::remove
+ bm_prefix<std::vector<int>>("ranges::remove(vector<int>) (prefix)", ranges_remove);
+ bm_sprinkled<std::vector<int>>("ranges::remove(vector<int>) (sprinkled)", ranges_remove);
+
+ bm_prefix<std::deque<int>>("ranges::remove(deque<int>) (prefix)", ranges_remove);
+ bm_sprinkled<std::deque<int>>("ranges::remove(deque<int>) (sprinkled)", ranges_remove);
+
+ bm_prefix<std::list<int>>("ranges::remove(list<int>) (prefix)", ranges_remove);
+ bm_sprinkled<std::list<int>>("ranges::remove(list<int>) (sprinkled)", ranges_remove);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
new file mode 100644
index 0000000000000..88c05384eb7bd
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove_copy) {
+ auto bench = [remove_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove_copy) {
+ auto bench = [remove_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_remove_copy = [](auto first, auto last, auto out, auto const& value) {
+ return std::remove_copy(first, last, out, value);
+ };
+ auto ranges_remove_copy = [](auto first, auto last, auto out, auto const& value) {
+ return std::ranges::remove_copy(first, last, out, value);
+ };
+
+ // std::remove_copy
+ bm_prefix<std::vector<int>>("std::remove_copy(vector<int>) (prefix)", std_remove_copy);
+ bm_sprinkled<std::vector<int>>("std::remove_copy(vector<int>) (sprinkled)", std_remove_copy);
+
+ bm_prefix<std::deque<int>>("std::remove_copy(deque<int>) (prefix)", std_remove_copy);
+ bm_sprinkled<std::deque<int>>("std::remove_copy(deque<int>) (sprinkled)", std_remove_copy);
+
+ bm_prefix<std::list<int>>("std::remove_copy(list<int>) (prefix)", std_remove_copy);
+ bm_sprinkled<std::list<int>>("std::remove_copy(list<int>) (sprinkled)", std_remove_copy);
+
+ // ranges::remove_copy
+ bm_prefix<std::vector<int>>("ranges::remove_copy(vector<int>) (prefix)", ranges_remove_copy);
+ bm_sprinkled<std::vector<int>>("ranges::remove_copy(vector<int>) (sprinkled)", ranges_remove_copy);
+
+ bm_prefix<std::deque<int>>("ranges::remove_copy(deque<int>) (prefix)", ranges_remove_copy);
+ bm_sprinkled<std::deque<int>>("ranges::remove_copy(deque<int>) (sprinkled)", ranges_remove_copy);
+
+ bm_prefix<std::list<int>>("ranges::remove_copy(list<int>) (prefix)", ranges_remove_copy);
+ bm_sprinkled<std::list<int>>("ranges::remove_copy(list<int>) (sprinkled)", ranges_remove_copy);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
new file mode 100644
index 0000000000000..95b0e93362bab
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -0,0 +1,119 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove_copy_if) {
+ auto bench = [remove_copy_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove_copy_if) {
+ auto bench = [remove_copy_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
+ return std::remove_copy_if(first, last, out, pred);
+ };
+ auto ranges_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
+ return std::ranges::remove_copy_if(first, last, out, pred);
+ };
+
+ // std::remove_copy_if
+ bm_prefix<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
+ bm_sprinkled<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
+
+ bm_prefix<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
+ bm_sprinkled<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
+
+ bm_prefix<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
+ bm_sprinkled<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
+
+ // ranges::remove_copy_if
+ bm_prefix<std::vector<int>>("ranges::remove_copy_if(vector<int>) (prefix)", ranges_remove_copy_if);
+ bm_sprinkled<std::vector<int>>("ranges::remove_copy_if(vector<int>) (sprinkled)", ranges_remove_copy_if);
+
+ bm_prefix<std::deque<int>>("ranges::remove_copy_if(deque<int>) (prefix)", ranges_remove_copy_if);
+ bm_sprinkled<std::deque<int>>("ranges::remove_copy_if(deque<int>) (sprinkled)", ranges_remove_copy_if);
+
+ bm_prefix<std::list<int>>("ranges::remove_copy_if(list<int>) (prefix)", ranges_remove_copy_if);
+ bm_sprinkled<std::list<int>>("ranges::remove_copy_if(list<int>) (sprinkled)", ranges_remove_copy_if);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
new file mode 100644
index 0000000000000..db0dabfbaa2c3
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove_if) {
+ auto bench = [remove_if](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove_if(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove_if) {
+ auto bench = [remove_if](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; ++i) {
+ *out++ = (i % 2 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove_if(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_remove_if = [](auto first, auto last, auto pred) { return std::remove_if(first, last, pred); };
+ auto ranges_remove_if = [](auto first, auto last, auto pred) { return std::ranges::remove_if(first, last, pred); };
+
+ // std::remove_if
+ bm_prefix<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
+ bm_sprinkled<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
+
+ bm_prefix<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
+ bm_sprinkled<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
+
+ bm_prefix<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
+ bm_sprinkled<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
+
+ // ranges::remove_if
+ bm_prefix<std::vector<int>>("ranges::remove_if(vector<int>) (prefix)", ranges_remove_if);
+ bm_sprinkled<std::vector<int>>("ranges::remove_if(vector<int>) (sprinkled)", ranges_remove_if);
+
+ bm_prefix<std::deque<int>>("ranges::remove_if(deque<int>) (prefix)", ranges_remove_if);
+ bm_sprinkled<std::deque<int>>("ranges::remove_if(deque<int>) (sprinkled)", ranges_remove_if);
+
+ bm_prefix<std::list<int>>("ranges::remove_if(list<int>) (prefix)", ranges_remove_if);
+ bm_sprinkled<std::list<int>>("ranges::remove_if(list<int>) (sprinkled)", ranges_remove_if);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
new file mode 100644
index 0000000000000..b55790d4db017
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -0,0 +1,107 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
+// into zzzzzzzzzzzyyyyyyyyyy and then back.
+//
+// This measures the performance of replace() when replacing a large
+// contiguous sequence of equal values.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation replace) {
+ auto bench = [replace](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
+
+ for ([[maybe_unused]] auto _ : st) {
+ replace(c.begin(), c.end(), x, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation replace) {
+ auto bench = [replace](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
+
+ for ([[maybe_unused]] auto _ : st) {
+ replace(c.begin(), c.end(), x, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_replace = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
+ auto ranges_replace = [](auto first, auto last, auto old, auto new_) {
+ return std::ranges::replace(first, last, old, new_);
+ };
+
+ // std::replace
+ bm_prefix<std::vector<int>>("std::replace(vector<int>) (prefix)", std_replace);
+ bm_sprinkled<std::vector<int>>("std::replace(vector<int>) (sprinkled)", std_replace);
+
+ bm_prefix<std::deque<int>>("std::replace(deque<int>) (prefix)", std_replace);
+ bm_sprinkled<std::deque<int>>("std::replace(deque<int>) (sprinkled)", std_replace);
+
+ bm_prefix<std::list<int>>("std::replace(list<int>) (prefix)", std_replace);
+ bm_sprinkled<std::list<int>>("std::replace(list<int>) (sprinkled)", std_replace);
+
+ // ranges::replace
+ bm_prefix<std::vector<int>>("ranges::replace(vector<int>) (prefix)", ranges_replace);
+ bm_sprinkled<std::vector<int>>("ranges::replace(vector<int>) (sprinkled)", ranges_replace);
+
+ bm_prefix<std::deque<int>>("ranges::replace(deque<int>) (prefix)", ranges_replace);
+ bm_sprinkled<std::deque<int>>("ranges::replace(deque<int>) (sprinkled)", ranges_replace);
+
+ bm_prefix<std::list<int>>("ranges::replace(list<int>) (prefix)", ranges_replace);
+ bm_sprinkled<std::list<int>>("ranges::replace(list<int>) (sprinkled)", ranges_replace);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
new file mode 100644
index 0000000000000..820cf08e5a901
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
+// into zzzzzzzzzzzyyyyyyyyyy and then back.
+//
+// This measures the performance of replace_if() when replacing a large
+// contiguous sequence of equal values.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation replace_if) {
+ auto bench = [replace_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto pred = [&x](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+ replace_if(c.begin(), c.end(), pred, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation replace_if) {
+ auto bench = [replace_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto pred = [&x](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+ replace_if(c.begin(), c.end(), pred, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_replace_if = [](auto first, auto last, auto pred, auto new_) {
+ return std::replace_if(first, last, pred, new_);
+ };
+ auto ranges_replace_if = [](auto first, auto last, auto pred, auto new_) {
+ return std::ranges::replace_if(first, last, pred, new_);
+ };
+
+ // std::replace_if
+ bm_prefix<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
+ bm_sprinkled<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
+
+ bm_prefix<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
+ bm_sprinkled<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
+
+ bm_prefix<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
+ bm_sprinkled<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
+
+ // ranges::replace_if
+ bm_prefix<std::vector<int>>("ranges::replace_if(vector<int>) (prefix)", ranges_replace_if);
+ bm_sprinkled<std::vector<int>>("ranges::replace_if(vector<int>) (sprinkled)", ranges_replace_if);
+
+ bm_prefix<std::deque<int>>("ranges::replace_if(deque<int>) (prefix)", ranges_replace_if);
+ bm_sprinkled<std::deque<int>>("ranges::replace_if(deque<int>) (sprinkled)", ranges_replace_if);
+
+ bm_prefix<std::list<int>>("ranges::replace_if(list<int>) (prefix)", ranges_replace_if);
+ bm_sprinkled<std::list<int>>("ranges::replace_if(list<int>) (sprinkled)", ranges_replace_if);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
new file mode 100644
index 0000000000000..dbb0d43d091c3
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation reverse) {
+ auto bench = [reverse](auto& st) {
+ std::size_t 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(); });
+
+ for ([[maybe_unused]] auto _ : st) {
+ reverse(c.begin(), c.end());
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
+}
+
+int main(int argc, char** argv) {
+ auto std_reverse = [](auto first, auto last) { return std::reverse(first, last); };
+ auto ranges_reverse = [](auto first, auto last) { return std::ranges::reverse(first, last); };
+
+ // std::reverse
+ bm<std::vector<int>>("std::reverse(vector<int>)", std_reverse);
+ bm<std::deque<int>>("std::reverse(deque<int>)", std_reverse);
+ bm<std::list<int>>("std::reverse(list<int>)", std_reverse);
+
+ // ranges::reverse
+ bm<std::vector<int>>("ranges::reverse(vector<int>)", ranges_reverse);
+ bm<std::deque<int>>("ranges::reverse(deque<int>)", ranges_reverse);
+ bm<std::list<int>>("ranges::reverse(list<int>)", ranges_reverse);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
new file mode 100644
index 0000000000000..84322fbfff40c
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation reverse_copy) {
+ auto bench = [reverse_copy](auto& st) {
+ std::size_t 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) {
+ reverse_copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
+}
+
+int main(int argc, char** argv) {
+ auto std_reverse_copy = [](auto first, auto last, auto out) { return std::reverse_copy(first, last, out); };
+ auto ranges_reverse_copy = [](auto first, auto last, auto out) {
+ return std::ranges::reverse_copy(first, last, out);
+ };
+
+ // std::reverse_copy
+ bm<std::vector<int>>("std::reverse_copy(vector<int>)", std_reverse_copy);
+ bm<std::deque<int>>("std::reverse_copy(deque<int>)", std_reverse_copy);
+ bm<std::list<int>>("std::reverse_copy(list<int>)", std_reverse_copy);
+
+ // ranges::reverse_copy
+ bm<std::vector<int>>("ranges::reverse_copy(vector<int>)", ranges_reverse_copy);
+ bm<std::deque<int>>("ranges::reverse_copy(deque<int>)", ranges_reverse_copy);
+ bm<std::list<int>>("ranges::reverse_copy(list<int>)", ranges_reverse_copy);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
new file mode 100644
index 0000000000000..eb91a011d863a
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation rotate) {
+ auto bench = [rotate](auto& st) {
+ std::size_t 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(); });
+
+ auto middle = std::next(c.begin(), size / 2);
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = rotate(c.begin(), middle, c.end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_rotate = [](auto first, auto middle, auto last) { return std::rotate(first, middle, last); };
+ auto ranges_rotate = [](auto first, auto middle, auto last) { return std::ranges::rotate(first, middle, last); };
+
+ // std::rotate
+ bm<std::vector<int>>("std::rotate(vector<int>)", std_rotate);
+ bm<std::deque<int>>("std::rotate(deque<int>)", std_rotate);
+ bm<std::list<int>>("std::rotate(list<int>)", std_rotate);
+
+ // ranges::rotate
+ bm<std::vector<int>>("ranges::rotate(vector<int>)", ranges_rotate);
+ bm<std::deque<int>>("ranges::rotate(deque<int>)", ranges_rotate);
+ bm<std::list<int>>("ranges::rotate(list<int>)", ranges_rotate);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
new file mode 100644
index 0000000000000..f5c14640fa87d
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation rotate_copy) {
+ auto bench = [rotate_copy](auto& st) {
+ std::size_t 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);
+
+ auto middle = std::next(c.begin(), size / 2);
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_rotate_copy = [](auto first, auto middle, auto last, auto out) {
+ return std::rotate_copy(first, middle, last, out);
+ };
+ auto ranges_rotate_copy = [](auto first, auto middle, auto last, auto out) {
+ return std::ranges::rotate_copy(first, middle, last, out);
+ };
+
+ // std::rotate_copy
+ bm<std::vector<int>>("std::rotate_copy(vector<int>)", std_rotate_copy);
+ bm<std::deque<int>>("std::rotate_copy(deque<int>)", std_rotate_copy);
+ bm<std::list<int>>("std::rotate_copy(list<int>)", std_rotate_copy);
+
+ // ranges::rotate_copy
+ bm<std::vector<int>>("ranges::rotate_copy(vector<int>)", ranges_rotate_copy);
+ bm<std::deque<int>>("ranges::rotate_copy(deque<int>)", ranges_rotate_copy);
+ bm<std::list<int>>("ranges::rotate_copy(list<int>)", ranges_rotate_copy);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
new file mode 100644
index 0000000000000..5f783efe8f627
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <random>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation sample) {
+ auto bench = [sample](auto& st) {
+ std::size_t 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);
+ auto const n = size / 4; // sample 1/4 of the range
+ std::mt19937 rng;
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
+ return std::sample(first, last, out, n, rng);
+ };
+ auto ranges_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
+ return std::ranges::sample(first, last, out, n, rng);
+ };
+
+ // std::sample
+ bm<std::vector<int>>("std::sample(vector<int>)", std_sample);
+ bm<std::deque<int>>("std::sample(deque<int>)", std_sample);
+ bm<std::list<int>>("std::sample(list<int>)", std_sample);
+
+ // ranges::sample
+ bm<std::vector<int>>("ranges::sample(vector<int>)", ranges_sample);
+ bm<std::deque<int>>("ranges::sample(deque<int>)", ranges_sample);
+ bm<std::list<int>>("ranges::sample(list<int>)", ranges_sample);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
new file mode 100644
index 0000000000000..9cf428f67e03e
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation shift_left) {
+ auto bench = [shift_left](auto& st) {
+ std::size_t 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(); });
+
+ auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = shift_left(c.begin(), c.end(), n);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_shift_left = [](auto first, auto last, auto n) { return std::shift_left(first, last, n); };
+
+ // std::shift_left
+ bm<std::vector<int>>("std::shift_left(vector<int>)", std_shift_left);
+ bm<std::deque<int>>("std::shift_left(deque<int>)", std_shift_left);
+ bm<std::list<int>>("std::shift_left(list<int>)", std_shift_left);
+
+ // ranges::shift_left not implemented yet
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
new file mode 100644
index 0000000000000..31a980ebdc5c1
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation shift_right) {
+ auto bench = [shift_right](auto& st) {
+ std::size_t 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(); });
+
+ auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = shift_right(c.begin(), c.end(), n);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_shift_right = [](auto first, auto last, auto n) { return std::shift_right(first, last, n); };
+
+ // std::shift_right
+ bm<std::vector<int>>("std::shift_right(vector<int>)", std_shift_right);
+ bm<std::deque<int>>("std::shift_right(deque<int>)", std_shift_right);
+ bm<std::list<int>>("std::shift_right(list<int>)", std_shift_right);
+
+ // ranges::shift_right not implemented yet
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
new file mode 100644
index 0000000000000..cc483b631c2a4
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <random>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation shuffle) {
+ auto bench = [shuffle](auto& st) {
+ std::size_t 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::mt19937 rng;
+
+ for ([[maybe_unused]] auto _ : st) {
+ shuffle(c.begin(), c.end(), rng);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_shuffle = [](auto first, auto last, auto& rng) { return std::shuffle(first, last, rng); };
+ auto ranges_shuffle = [](auto first, auto last, auto& rng) { return std::ranges::shuffle(first, last, rng); };
+
+ // std::shuffle
+ bm<std::vector<int>>("std::shuffle(vector<int>)", std_shuffle);
+ bm<std::deque<int>>("std::shuffle(deque<int>)", std_shuffle);
+
+ // ranges::shuffle
+ bm<std::vector<int>>("ranges::shuffle(vector<int>)", ranges_shuffle);
+ bm<std::deque<int>>("ranges::shuffle(deque<int>)", ranges_shuffle);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
new file mode 100644
index 0000000000000..05b733fecc70d
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation swap_ranges) {
+ auto bench = [swap_ranges](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1, c2;
+ std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c1);
+ benchmark::DoNotOptimize(c2);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_swap_ranges = [](auto first1, auto last1, auto first2, auto) {
+ return std::swap_ranges(first1, last1, first2);
+ };
+ auto ranges_swap_ranges = [](auto first1, auto last1, auto first2, auto last2) {
+ return std::ranges::swap_ranges(first1, last1, first2, last2);
+ };
+
+ // std::swap_ranges
+ bm<std::vector<int>>("std::swap_ranges(vector<int>)", std_swap_ranges);
+ bm<std::deque<int>>("std::swap_ranges(deque<int>)", std_swap_ranges);
+ bm<std::list<int>>("std::swap_ranges(list<int>)", std_swap_ranges);
+
+ // ranges::swap_ranges
+ bm<std::vector<int>>("ranges::swap_ranges(vector<int>)", ranges_swap_ranges);
+ bm<std::deque<int>>("ranges::swap_ranges(deque<int>)", ranges_swap_ranges);
+ bm<std::list<int>>("ranges::swap_ranges(list<int>)", ranges_swap_ranges);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
new file mode 100644
index 0000000000000..bdc913356d3c9
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation transform) {
+ auto bench = [transform](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1, c2;
+ std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+ std::vector<ValueType> out(size);
+
+ auto f = [](auto& x, auto& y) {
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ return x + y;
+ };
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c1);
+ benchmark::DoNotOptimize(c2);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_transform = [](auto first1, auto last1, auto first2, auto, auto out, auto f) {
+ return std::transform(first1, last1, first2, out, f);
+ };
+ auto ranges_transform = [](auto first1, auto last1, auto first2, auto last2, auto out, auto f) {
+ return std::ranges::transform(first1, last1, first2, last2, out, f);
+ };
+
+ // std::transform
+ bm<std::vector<int>>("std::transform(vector<int>, vector<int>)", std_transform);
+ bm<std::deque<int>>("std::transform(deque<int>, deque<int>)", std_transform);
+ bm<std::list<int>>("std::transform(list<int>, list<int>)", std_transform);
+
+ // ranges::transform
+ bm<std::vector<int>>("ranges::transform(vector<int>, vector<int>)", ranges_transform);
+ bm<std::deque<int>>("ranges::transform(deque<int>, deque<int>)", ranges_transform);
+ bm<std::list<int>>("ranges::transform(list<int>, list<int>)", ranges_transform);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
new file mode 100644
index 0000000000000..6cf56368f63f3
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation transform) {
+ auto bench = [transform](auto& st) {
+ std::size_t 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);
+
+ auto f = [](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element;
+ };
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = transform(c.begin(), c.end(), out.begin(), f);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_transform = [](auto first, auto last, auto out, auto f) { return std::transform(first, last, out, f); };
+ auto ranges_transform = [](auto first, auto last, auto out, auto f) {
+ return std::ranges::transform(first, last, out, f);
+ };
+
+ // std::transform
+ bm<std::vector<int>>("std::transform(vector<int>) (identity transform)", std_transform);
+ bm<std::deque<int>>("std::transform(deque<int>) (identity transform)", std_transform);
+ bm<std::list<int>>("std::transform(list<int>) (identity transform)", std_transform);
+
+ // ranges::transform
+ bm<std::vector<int>>("ranges::transform(vector<int>) (identity transform)", ranges_transform);
+ bm<std::deque<int>>("ranges::transform(deque<int>) (identity transform)", ranges_transform);
+ bm<std::list<int>>("ranges::transform(list<int>) (identity transform)", ranges_transform);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
new file mode 100644
index 0000000000000..1d9cca2f60688
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -0,0 +1,132 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique) {
+ auto bench = [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique) {
+ auto bench = [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_unique = [](auto first, auto last) { return std::unique(first, last); };
+ auto ranges_unique = [](auto first, auto last) { return std::ranges::unique(first, last); };
+
+ // std::unique
+ bm_contiguous<std::vector<int>>("std::unique(vector<int>) (contiguous)", std_unique);
+ bm_sprinkled<std::vector<int>>("std::unique(vector<int>) (sprinkled)", std_unique);
+
+ bm_contiguous<std::deque<int>>("std::unique(deque<int>) (contiguous)", std_unique);
+ bm_sprinkled<std::deque<int>>("std::unique(deque<int>) (sprinkled)", std_unique);
+
+ bm_contiguous<std::list<int>>("std::unique(list<int>) (contiguous)", std_unique);
+ bm_sprinkled<std::list<int>>("std::unique(list<int>) (sprinkled)", std_unique);
+
+ // ranges::unique
+ bm_contiguous<std::vector<int>>("ranges::unique(vector<int>) (contiguous)", ranges_unique);
+ bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>) (sprinkled)", ranges_unique);
+
+ bm_contiguous<std::deque<int>>("ranges::unique(deque<int>) (contiguous)", ranges_unique);
+ bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>) (sprinkled)", ranges_unique);
+
+ bm_contiguous<std::list<int>>("ranges::unique(list<int>) (contiguous)", ranges_unique);
+ bm_sprinkled<std::list<int>>("ranges::unique(list<int>) (sprinkled)", ranges_unique);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
new file mode 100644
index 0000000000000..c7b217ffd960d
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.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 <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique_copy) {
+ auto bench = [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique_copy) {
+ auto bench = [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ alternate(c.begin(), size);
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
+ auto ranges_unique_copy = [](auto first, auto last, auto out) { return std::ranges::unique_copy(first, last, out); };
+
+ // std::unique_copy
+ bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);
+ bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);
+
+ bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);
+ bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);
+
+ bm_contiguous<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);
+ bm_sprinkled<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);
+
+ // ranges::unique_copy
+ bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>) (contiguous)", ranges_unique_copy);
+ bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>) (sprinkled)", ranges_unique_copy);
+
+ bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>) (contiguous)", ranges_unique_copy);
+ bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>) (sprinkled)", ranges_unique_copy);
+
+ bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>) (contiguous)", ranges_unique_copy);
+ bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>) (sprinkled)", ranges_unique_copy);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
new file mode 100644
index 0000000000000..24ca442fb3de4
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique_copy) {
+ auto bench = [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+ std::vector<ValueType> out(size);
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique_copy) {
+ auto bench = [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ alternate(c.begin(), size);
+
+ std::vector<ValueType> out(size);
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_unique_copy = [](auto first, auto last, auto out, auto pred) {
+ return std::unique_copy(first, last, out, pred);
+ };
+ auto ranges_unique_copy = [](auto first, auto last, auto out, auto pred) {
+ return std::ranges::unique_copy(first, last, out, pred);
+ };
+
+ // std::unique_copy
+ bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy);
+ bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy);
+
+ bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy);
+ bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy);
+
+ bm_contiguous<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy);
+ bm_sprinkled<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy);
+
+ // ranges::unique_copy
+ bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (contiguous)", ranges_unique_copy);
+ bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (sprinkled)", ranges_unique_copy);
+
+ bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (contiguous)", ranges_unique_copy);
+ bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (sprinkled)", ranges_unique_copy);
+
+ bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>, pred) (contiguous)", ranges_unique_copy);
+ bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>, pred) (sprinkled)", ranges_unique_copy);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
new file mode 100644
index 0000000000000..0b258ea5cbecc
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -0,0 +1,144 @@
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique) {
+ auto bench = [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique) {
+ auto bench = [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ };
+ benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+ auto std_unique = [](auto first, auto last, auto pred) { return std::unique(first, last, pred); };
+ auto ranges_unique = [](auto first, auto last, auto pred) { return std::ranges::unique(first, last, pred); };
+
+ // std::unique
+ bm_contiguous<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique);
+ bm_sprinkled<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique);
+
+ bm_contiguous<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique);
+ bm_sprinkled<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique);
+
+ bm_contiguous<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique);
+ bm_sprinkled<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique);
+
+ // ranges::unique
+ bm_contiguous<std::vector<int>>("ranges::unique(vector<int>, pred) (contiguous)", ranges_unique);
+ bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>, pred) (sprinkled)", ranges_unique);
+
+ bm_contiguous<std::deque<int>>("ranges::unique(deque<int>, pred) (contiguous)", ranges_unique);
+ bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>, pred) (sprinkled)", ranges_unique);
+
+ bm_contiguous<std::list<int>>("ranges::unique(list<int>, pred) (contiguous)", ranges_unique);
+ bm_sprinkled<std::list<int>>("ranges::unique(list<int>, pred) (sprinkled)", ranges_unique);
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/reverse.bench.cpp
deleted file mode 100644
index 2d8dd819ac24c..0000000000000
--- a/libcxx/test/benchmarks/algorithms/reverse.bench.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-
-#include <algorithm>
-#include <iterator>
-#include <string>
-#include <vector>
-
-#include <benchmark/benchmark.h>
-#include "../GenerateInput.h"
-
-template <class T>
-static void bm_reverse(benchmark::State& state) {
- std::size_t const n = state.range();
- std::vector<T> vec;
- std::generate_n(std::back_inserter(vec), n, [] { return Generate<T>::cheap(); });
- for (auto _ : state) {
- std::reverse(vec.begin(), vec.end());
- benchmark::DoNotOptimize(vec);
- }
-}
-BENCHMARK(bm_reverse<int>)->Name("std::reverse(vector<int>)")->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_reverse<std::string>)->Name("std::reverse(vector<string>)")->DenseRange(1, 8)->Range(16, 1 << 20);
-
-template <class T>
-static void bm_ranges_reverse(benchmark::State& state) {
- std::size_t const n = state.range();
- std::vector<T> vec;
- std::generate_n(std::back_inserter(vec), n, [] { return Generate<T>::cheap(); });
- for (auto _ : state) {
- std::ranges::reverse(vec.begin(), vec.end());
- benchmark::DoNotOptimize(vec);
- }
-}
-BENCHMARK(bm_ranges_reverse<int>)->Name("ranges::reverse(vector<int>)")->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_ranges_reverse<std::string>)
- ->Name("ranges::reverse(vector<string>)")
- ->DenseRange(1, 8)
- ->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
>From b86aa95e1d7daa3ddf78c3de5dfa29bc434f1cfc Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 15:10:48 -0500
Subject: [PATCH 2/4] Add move_backward
---
.../algorithms/modifying/move.bench.cpp | 91 +++++++++++++++++++
.../modifying/move_backward.bench.cpp | 91 +++++++++++++++++++
.../test/benchmarks/algorithms/move.bench.cpp | 71 ---------------
.../algorithms/move_backward.bench.cpp | 71 ---------------
4 files changed, 182 insertions(+), 142 deletions(-)
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
create mode 100644 libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
delete mode 100644 libcxx/test/benchmarks/algorithms/move.bench.cpp
delete mode 100644 libcxx/test/benchmarks/algorithms/move_backward.bench.cpp
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
new file mode 100644
index 0000000000000..f009850dac215
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_move = [](auto first, auto last, auto out) { return std::move(first, last, out); };
+
+ // {std,ranges}::move(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto move) {
+ benchmark::RegisterBenchmark(name, [move](auto& st) {
+ std::size_t const n = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1(n), c2(n);
+ std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+
+ Container* in = &c1;
+ Container* out = &c2;
+ for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c1);
+ benchmark::DoNotOptimize(c2);
+ auto result = move(in->begin(), in->end(), out->begin());
+ benchmark::DoNotOptimize(result);
+ std::swap(in, out);
+ }
+ })->Range(8, 1 << 20);
+ };
+ bm.operator()<std::vector<int>>("std::move(vector<int>)", std_move);
+ bm.operator()<std::deque<int>>("std::move(deque<int>)", std_move);
+ bm.operator()<std::list<int>>("std::move(list<int>)", std_move);
+ bm.operator()<std::vector<int>>("rng::move(vector<int>)", std::ranges::move);
+ bm.operator()<std::deque<int>>("rng::move(deque<int>)", std::ranges::move);
+ bm.operator()<std::list<int>>("rng::move(list<int>)", std::ranges::move);
+ }
+
+ // {std,ranges}::move(vector<bool>)
+ {
+ auto bm = []<bool Aligned>(std::string name, auto move) {
+ benchmark::RegisterBenchmark(name, [move](auto& st) {
+ std::size_t const n = st.range(0);
+ std::vector<bool> c1(n, true);
+ std::vector<bool> c2(n, false);
+
+ std::vector<bool>* in = &c1;
+ std::vector<bool>* out = &c2;
+ for (auto _ : st) {
+ auto first1 = in->begin();
+ auto last1 = in->end();
+ auto first2 = out->begin();
+ if constexpr (Aligned) {
+ benchmark::DoNotOptimize(move(first1, last1, first2));
+ } else {
+ benchmark::DoNotOptimize(move(first1 + 4, last1, first2));
+ }
+ std::swap(in, out);
+ benchmark::DoNotOptimize(in);
+ benchmark::DoNotOptimize(out);
+ }
+ })->Range(64, 1 << 20);
+ };
+ bm.operator()<true>("std::move(vector<bool>) (aligned)", std_move);
+ bm.operator()<false>("std::move(vector<bool>) (unaligned)", std_move);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+ bm.operator()<true>("rng::move(vector<bool>) (aligned)", std::ranges::move);
+ bm.operator()<false>("rng::move(vector<bool>) (unaligned)", std::ranges::move);
+#endif
+ }
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
new file mode 100644
index 0000000000000..ef9373cbcdd72
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_move_backward = [](auto first, auto last, auto out) { return std::move_backward(first, last, out); };
+
+ // {std,ranges}::move_backward(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto move_backward) {
+ benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
+ std::size_t const n = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1(n), c2(n);
+ std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+
+ Container* in = &c1;
+ Container* out = &c2;
+ for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c1);
+ benchmark::DoNotOptimize(c2);
+ auto result = move_backward(in->begin(), in->end(), out->end());
+ benchmark::DoNotOptimize(result);
+ std::swap(in, out);
+ }
+ })->Range(8, 1 << 20);
+ };
+ bm.operator()<std::vector<int>>("std::move_backward(vector<int>)", std_move_backward);
+ bm.operator()<std::deque<int>>("std::move_backward(deque<int>)", std_move_backward);
+ bm.operator()<std::list<int>>("std::move_backward(list<int>)", std_move_backward);
+ bm.operator()<std::vector<int>>("rng::move_backward(vector<int>)", std::ranges::move_backward);
+ bm.operator()<std::deque<int>>("rng::move_backward(deque<int>)", std::ranges::move_backward);
+ bm.operator()<std::list<int>>("rng::move_backward(list<int>)", std::ranges::move_backward);
+ }
+
+ // {std,ranges}::move_backward(vector<bool>)
+ {
+ auto bm = []<bool Aligned>(std::string name, auto move_backward) {
+ benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
+ std::size_t const n = st.range(0);
+ std::vector<bool> c1(n, true);
+ std::vector<bool> c2(n, false);
+
+ std::vector<bool>* in = &c1;
+ std::vector<bool>* out = &c2;
+ for (auto _ : st) {
+ auto first1 = in->begin();
+ auto last1 = in->end();
+ auto last2 = out->end();
+ if constexpr (Aligned) {
+ benchmark::DoNotOptimize(move_backward(first1, last1, last2));
+ } else {
+ benchmark::DoNotOptimize(move_backward(first1, last1 - 4, last2));
+ }
+ std::swap(in, out);
+ benchmark::DoNotOptimize(in);
+ benchmark::DoNotOptimize(out);
+ }
+ })->Range(64, 1 << 20);
+ };
+ bm.operator()<true>("std::move_backward(vector<bool>) (aligned)", std_move_backward);
+ bm.operator()<false>("std::move_backward(vector<bool>) (unaligned)", std_move_backward);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+ bm.operator()<true>("rng::move_backward(vector<bool>) (aligned)", std::ranges::move_backward);
+ bm.operator()<false>("rng::move_backward(vector<bool>) (unaligned)", std::ranges::move_backward);
+#endif
+ }
+
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ benchmark::Shutdown();
+ return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/move.bench.cpp b/libcxx/test/benchmarks/algorithms/move.bench.cpp
deleted file mode 100644
index 73f36f0c129de..0000000000000
--- a/libcxx/test/benchmarks/algorithms/move.bench.cpp
+++ /dev/null
@@ -1,71 +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 <ranges>
-#include <vector>
-
-template <bool aligned>
-void bm_ranges_move_vb(benchmark::State& state) {
- auto n = state.range();
- std::vector<bool> v1(n, true);
- std::vector<bool> v2(n, false);
- benchmark::DoNotOptimize(v1);
- benchmark::DoNotOptimize(v2);
- std::vector<bool>* in = &v1;
- std::vector<bool>* out = &v2;
- for (auto _ : state) {
- if constexpr (aligned) {
- benchmark::DoNotOptimize(std::ranges::move(*in, std::ranges::begin(*out)));
- } else {
- benchmark::DoNotOptimize(
- std::ranges::move(std::views::counted(in->begin() + 4, n - 4), std::ranges::begin(*out)));
- }
- std::swap(in, out);
- benchmark::DoNotOptimize(in);
- benchmark::DoNotOptimize(out);
- }
-}
-
-template <bool aligned>
-void bm_move_vb(benchmark::State& state) {
- auto n = state.range();
- std::vector<bool> v1(n, true);
- std::vector<bool> v2(n, false);
- benchmark::DoNotOptimize(v1);
- benchmark::DoNotOptimize(v2);
- std::vector<bool>* in = &v1;
- std::vector<bool>* out = &v2;
- for (auto _ : state) {
- auto first1 = in->begin();
- auto last1 = in->end();
- auto first2 = out->begin();
- if constexpr (aligned) {
- benchmark::DoNotOptimize(std::move(first1, last1, first2));
- } else {
- benchmark::DoNotOptimize(std::move(first1 + 4, last1, first2));
- }
- std::swap(in, out);
- benchmark::DoNotOptimize(in);
- benchmark::DoNotOptimize(out);
- }
-}
-
-BENCHMARK(bm_ranges_move_vb<true>)
- ->Name("bm_ranges_move_vb_aligned")
- ->Range(8, 1 << 16)
- ->DenseRange(102400, 204800, 4096);
-BENCHMARK(bm_ranges_move_vb<false>)->Name("bm_ranges_move_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK(bm_move_vb<true>)->Name("bm_move_vb_aligned")->Range(8, 1 << 20);
-BENCHMARK(bm_move_vb<false>)->Name("bm_move_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/move_backward.bench.cpp
deleted file mode 100644
index 23d7395198419..0000000000000
--- a/libcxx/test/benchmarks/algorithms/move_backward.bench.cpp
+++ /dev/null
@@ -1,71 +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 <ranges>
-#include <vector>
-
-template <bool aligned>
-void bm_ranges_move_backward_vb(benchmark::State& state) {
- auto n = state.range();
- std::vector<bool> v1(n, true);
- std::vector<bool> v2(n, false);
- benchmark::DoNotOptimize(v1);
- benchmark::DoNotOptimize(v2);
- std::vector<bool>* in = &v1;
- std::vector<bool>* out = &v2;
- for (auto _ : state) {
- if constexpr (aligned) {
- benchmark::DoNotOptimize(std::ranges::move_backward(*in, std::ranges::end(*out)));
- } else {
- benchmark::DoNotOptimize(
- std::ranges::move_backward(std::views::counted(in->begin(), n - 4), std::ranges::end(*out)));
- }
- std::swap(in, out);
- benchmark::DoNotOptimize(in);
- benchmark::DoNotOptimize(out);
- }
-}
-
-template <bool aligned>
-void bm_move_backward_vb(benchmark::State& state) {
- auto n = state.range();
- std::vector<bool> v1(n, true);
- std::vector<bool> v2(n, false);
- benchmark::DoNotOptimize(v1);
- benchmark::DoNotOptimize(v2);
- std::vector<bool>* in = &v1;
- std::vector<bool>* out = &v2;
- for (auto _ : state) {
- auto first1 = in->begin();
- auto last1 = in->end();
- auto last2 = out->end();
- if constexpr (aligned) {
- benchmark::DoNotOptimize(std::move_backward(first1, last1, last2));
- } else {
- benchmark::DoNotOptimize(std::move_backward(first1, last1 - 4, last2));
- }
- std::swap(in, out);
- benchmark::DoNotOptimize(in);
- benchmark::DoNotOptimize(out);
- }
-}
-
-BENCHMARK(bm_ranges_move_backward_vb<true>)
- ->Name("bm_ranges_move_backward_vb_aligned")
- ->Range(8, 1 << 16)
- ->DenseRange(102400, 204800, 4096);
-BENCHMARK(bm_ranges_move_backward_vb<false>)->Name("bm_ranges_move_backward_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK(bm_move_backward_vb<true>)->Name("bm_move_backward_vb_aligned")->Range(8, 1 << 20);
-BENCHMARK(bm_move_backward_vb<false>)->Name("bm_move_backward_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK_MAIN();
>From 9fede1f1cda28145ecf0d8f086e9dbdee42f0336 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 16:12:19 -0500
Subject: [PATCH 3/4] Implement review comments from the std::copy code review
---
.../algorithms/modifying/fill.bench.cpp | 106 ++++----
.../algorithms/modifying/fill_n.bench.cpp | 106 ++++----
.../algorithms/modifying/generate.bench.cpp | 63 ++---
.../algorithms/modifying/generate_n.bench.cpp | 63 ++---
.../algorithms/modifying/remove.bench.cpp | 211 ++++++++--------
.../modifying/remove_copy.bench.cpp | 153 ++++++------
.../modifying/remove_copy_if.bench.cpp | 173 +++++++------
.../algorithms/modifying/remove_if.bench.cpp | 229 ++++++++---------
.../algorithms/modifying/replace.bench.cpp | 149 ++++++-----
.../algorithms/modifying/replace_if.bench.cpp | 163 ++++++------
.../algorithms/modifying/reverse.bench.cpp | 54 ++--
.../modifying/reverse_copy.bench.cpp | 60 ++---
.../algorithms/modifying/rotate.bench.cpp | 63 ++---
.../modifying/rotate_copy.bench.cpp | 63 +++--
.../algorithms/modifying/sample.bench.cpp | 67 +++--
.../algorithms/modifying/shift_left.bench.cpp | 55 +++--
.../modifying/shift_right.bench.cpp | 55 +++--
.../algorithms/modifying/shuffle.bench.cpp | 57 ++---
.../modifying/swap_ranges.bench.cpp | 63 +++--
.../modifying/transform.binary.bench.cpp | 79 +++---
.../modifying/transform.unary.bench.cpp | 73 +++---
.../algorithms/modifying/unique.bench.cpp | 209 ++++++++--------
.../modifying/unique_copy.bench.cpp | 155 ++++++------
.../modifying/unique_copy_pred.bench.cpp | 177 +++++++-------
.../modifying/unique_pred.bench.cpp | 231 +++++++++---------
25 files changed, 1438 insertions(+), 1439 deletions(-)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
index 64c7364be6549..fb0fa8ffc5c69 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
@@ -20,64 +20,66 @@
#include "../../GenerateInput.h"
#include "test_macros.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation fill) {
- auto bench = [fill](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- Container c(size, y);
-
- for ([[maybe_unused]] auto _ : st) {
- fill(c.begin(), c.end(), x);
- std::swap(x, y);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-template <class Operation>
-void bm_vector_bool(std::string operation_name, Operation fill) {
- auto bench = [fill](auto& st) {
- std::size_t const size = st.range(0);
- bool x = true;
- bool y = false;
- std::vector<bool> c(size, y);
+int main(int argc, char** argv) {
+ auto std_fill = [](auto first, auto last, auto const& value) { return std::fill(first, last, value); };
- for ([[maybe_unused]] auto _ : st) {
- fill(c.begin(), c.end(), x);
- std::swap(x, y);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
+ // {std,ranges}::fill(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto fill) {
+ benchmark::RegisterBenchmark(
+ name,
+ [fill](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ Container c(size, y);
-int main(int argc, char** argv) {
- auto std_fill = [](auto first, auto last, auto const& value) { return std::fill(first, last, value); };
- auto ranges_fill = [](auto first, auto last, auto const& value) { return std::ranges::fill(first, last, value); };
+ for ([[maybe_unused]] auto _ : st) {
+ fill(c.begin(), c.end(), x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::fill(vector<int>)", std_fill);
+ bm.operator()<std::deque<int>>("std::fill(deque<int>)", std_fill);
+ bm.operator()<std::list<int>>("std::fill(list<int>)", std_fill);
+ bm.operator()<std::vector<int>>("rng::fill(vector<int>)", std::ranges::fill);
+ bm.operator()<std::deque<int>>("rng::fill(deque<int>)", std::ranges::fill);
+ bm.operator()<std::list<int>>("rng::fill(list<int>)", std::ranges::fill);
+ }
- // std::fill
- bm<std::vector<int>>("std::fill(vector<int>)", std_fill);
- bm<std::deque<int>>("std::fill(deque<int>)", std_fill);
- bm<std::list<int>>("std::fill(list<int>)", std_fill);
- bm_vector_bool("std::fill(vector<bool>)", std_fill);
+ // {std,ranges}::fill(vector<bool>)
+ {
+ auto bm = [](std::string name, auto fill) {
+ benchmark::RegisterBenchmark(name, [fill](auto& st) {
+ std::size_t const size = st.range(0);
+ bool x = true;
+ bool y = false;
+ std::vector<bool> c(size, y);
- // ranges::fill
- bm<std::vector<int>>("ranges::fill(vector<int>)", ranges_fill);
- bm<std::deque<int>>("ranges::fill(deque<int>)", ranges_fill);
- bm<std::list<int>>("ranges::fill(list<int>)", ranges_fill);
+ for ([[maybe_unused]] auto _ : st) {
+ fill(c.begin(), c.end(), x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ })->Range(64, 1 << 20);
+ };
+ bm("std::fill(vector<bool>)", std_fill);
#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
- bm_vector_bool("ranges::fill(vector<bool>)", ranges_fill);
+ bm("rng::fill(vector<bool>)", std::ranges::fill);
#endif
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
index aaeb0982956f9..d4ca98e623871 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
@@ -20,64 +20,66 @@
#include "../../GenerateInput.h"
#include "test_macros.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation fill_n) {
- auto bench = [fill_n](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- Container c(size, y);
-
- for ([[maybe_unused]] auto _ : st) {
- fill_n(c.begin(), size, x);
- std::swap(x, y);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-template <class Operation>
-void bm_vector_bool(std::string operation_name, Operation fill_n) {
- auto bench = [fill_n](auto& st) {
- std::size_t const size = st.range(0);
- bool x = true;
- bool y = false;
- std::vector<bool> c(size, y);
+int main(int argc, char** argv) {
+ auto std_fill_n = [](auto out, auto n, auto const& value) { return std::fill_n(out, n, value); };
- for ([[maybe_unused]] auto _ : st) {
- fill_n(c.begin(), size, x);
- std::swap(x, y);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
+ // {std,ranges}::fill_n(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto fill_n) {
+ benchmark::RegisterBenchmark(
+ name,
+ [fill_n](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ Container c(size, y);
-int main(int argc, char** argv) {
- auto std_fill_n = [](auto out, auto n, auto const& value) { return std::fill_n(out, n, value); };
- auto ranges_fill_n = [](auto out, auto n, auto const& value) { return std::ranges::fill_n(out, n, value); };
+ for ([[maybe_unused]] auto _ : st) {
+ fill_n(c.begin(), size, x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::fill_n(vector<int>)", std_fill_n);
+ bm.operator()<std::deque<int>>("std::fill_n(deque<int>)", std_fill_n);
+ bm.operator()<std::list<int>>("std::fill_n(list<int>)", std_fill_n);
+ bm.operator()<std::vector<int>>("rng::fill_n(vector<int>)", std::ranges::fill_n);
+ bm.operator()<std::deque<int>>("rng::fill_n(deque<int>)", std::ranges::fill_n);
+ bm.operator()<std::list<int>>("rng::fill_n(list<int>)", std::ranges::fill_n);
+ }
- // std::fill_n
- bm<std::vector<int>>("std::fill_n(vector<int>)", std_fill_n);
- bm<std::deque<int>>("std::fill_n(deque<int>)", std_fill_n);
- bm<std::list<int>>("std::fill_n(list<int>)", std_fill_n);
- bm_vector_bool("std::fill_n(vector<bool>)", std_fill_n);
+ // {std,ranges}::fill_n(vector<bool>)
+ {
+ auto bm = [](std::string name, auto fill_n) {
+ benchmark::RegisterBenchmark(name, [fill_n](auto& st) {
+ std::size_t const size = st.range(0);
+ bool x = true;
+ bool y = false;
+ std::vector<bool> c(size, y);
- // ranges::fill_n
- bm<std::vector<int>>("ranges::fill_n(vector<int>)", ranges_fill_n);
- bm<std::deque<int>>("ranges::fill_n(deque<int>)", ranges_fill_n);
- bm<std::list<int>>("ranges::fill_n(list<int>)", ranges_fill_n);
+ for ([[maybe_unused]] auto _ : st) {
+ fill_n(c.begin(), size, x);
+ std::swap(x, y);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ benchmark::ClobberMemory();
+ }
+ })->Range(64, 1 << 20);
+ };
+ bm("std::fill_n(vector<bool>)", std_fill_n);
#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
- bm_vector_bool("ranges::fill_n(vector<bool>)", ranges_fill_n);
+ bm("rng::fill_n(vector<bool>)", std::ranges::fill_n);
#endif
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
index 15b039a4d3009..9056d598d5d38 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
@@ -19,38 +19,39 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation generate) {
- auto bench = [generate](auto& st) {
- std::size_t const size = st.range(0);
- Container c(size);
- using ValueType = typename Container::value_type;
- ValueType x = Generate<ValueType>::random();
-
- for ([[maybe_unused]] auto _ : st) {
- auto f = [&x] { return x; };
- generate(c.begin(), c.end(), f);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_generate = [](auto first, auto last, auto f) { return std::generate(first, last, f); };
- auto ranges_generate = [](auto first, auto last, auto f) { return std::ranges::generate(first, last, f); };
-
- // std::generate
- bm<std::vector<int>>("std::generate(vector<int>)", std_generate);
- bm<std::deque<int>>("std::generate(deque<int>)", std_generate);
- bm<std::list<int>>("std::generate(list<int>)", std_generate);
-
- // ranges::generate
- bm<std::vector<int>>("ranges::generate(vector<int>)", ranges_generate);
- bm<std::deque<int>>("ranges::generate(deque<int>)", ranges_generate);
- bm<std::list<int>>("ranges::generate(list<int>)", ranges_generate);
+ auto std_generate = [](auto first, auto last, auto f) { return std::generate(first, last, f); };
+
+ // {std,ranges}::generate
+ {
+ auto bm = []<class Container>(std::string name, auto generate) {
+ benchmark::RegisterBenchmark(
+ name,
+ [generate](auto& st) {
+ std::size_t const size = st.range(0);
+ Container c(size);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto f = [&x] { return x; };
+ generate(c.begin(), c.end(), f);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::generate(vector<int>)", std_generate);
+ bm.operator()<std::deque<int>>("std::generate(deque<int>)", std_generate);
+ bm.operator()<std::list<int>>("std::generate(list<int>)", std_generate);
+ bm.operator()<std::vector<int>>("rng::generate(vector<int>)", std::ranges::generate);
+ bm.operator()<std::deque<int>>("rng::generate(deque<int>)", std::ranges::generate);
+ bm.operator()<std::list<int>>("rng::generate(list<int>)", std::ranges::generate);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
index 75b088411810f..d33d9183dcb42 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
@@ -19,38 +19,39 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation generate_n) {
- auto bench = [generate_n](auto& st) {
- std::size_t const size = st.range(0);
- Container c(size);
- using ValueType = typename Container::value_type;
- ValueType x = Generate<ValueType>::random();
-
- for ([[maybe_unused]] auto _ : st) {
- auto f = [&x] { return x; };
- generate_n(c.begin(), size, f);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_generate_n = [](auto out, auto n, auto f) { return std::generate_n(out, n, f); };
- auto ranges_generate_n = [](auto out, auto n, auto f) { return std::ranges::generate_n(out, n, f); };
-
- // std::generate_n
- bm<std::vector<int>>("std::generate_n(vector<int>)", std_generate_n);
- bm<std::deque<int>>("std::generate_n(deque<int>)", std_generate_n);
- bm<std::list<int>>("std::generate_n(list<int>)", std_generate_n);
-
- // ranges::generate_n
- bm<std::vector<int>>("ranges::generate_n(vector<int>)", ranges_generate_n);
- bm<std::deque<int>>("ranges::generate_n(deque<int>)", ranges_generate_n);
- bm<std::list<int>>("ranges::generate_n(list<int>)", ranges_generate_n);
+ auto std_generate_n = [](auto out, auto n, auto f) { return std::generate_n(out, n, f); };
+
+ // {std,ranges}::generate_n
+ {
+ auto bm = []<class Container>(std::string name, auto generate_n) {
+ benchmark::RegisterBenchmark(
+ name,
+ [generate_n](auto& st) {
+ std::size_t const size = st.range(0);
+ Container c(size);
+ using ValueType = typename Container::value_type;
+ ValueType x = Generate<ValueType>::random();
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto f = [&x] { return x; };
+ generate_n(c.begin(), size, f);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::generate_n(vector<int>)", std_generate_n);
+ bm.operator()<std::deque<int>>("std::generate_n(deque<int>)", std_generate_n);
+ bm.operator()<std::list<int>>("std::generate_n(list<int>)", std_generate_n);
+ bm.operator()<std::vector<int>>("rng::generate_n(vector<int>)", std::ranges::generate_n);
+ bm.operator()<std::deque<int>>("rng::generate_n(deque<int>)", std::ranges::generate_n);
+ bm.operator()<std::list<int>>("rng::generate_n(list<int>)", std::ranges::generate_n);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index 764dfe73ab70c..956753de13edc 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -19,112 +19,113 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove) {
- auto bench = [remove](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = remove(c[i].begin(), c[i].end(), x);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove) {
- auto bench = [remove](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto alternate = [&](auto out, auto n) {
- for (std::size_t i = 0; i != n; ++i) {
- *out++ = (i % 2 == 0 ? x : y);
- }
- };
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- alternate(c[i].begin(), size);
- }
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = remove(c[i].begin(), c[i].end(), x);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- alternate(c[i].begin(), size);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_remove = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
- auto ranges_remove = [](auto first, auto last, auto const& value) { return std::ranges::remove(first, last, value); };
-
- // std::remove
- bm_prefix<std::vector<int>>("std::remove(vector<int>) (prefix)", std_remove);
- bm_sprinkled<std::vector<int>>("std::remove(vector<int>) (sprinkled)", std_remove);
-
- bm_prefix<std::deque<int>>("std::remove(deque<int>) (prefix)", std_remove);
- bm_sprinkled<std::deque<int>>("std::remove(deque<int>) (sprinkled)", std_remove);
-
- bm_prefix<std::list<int>>("std::remove(list<int>) (prefix)", std_remove);
- bm_sprinkled<std::list<int>>("std::remove(list<int>) (sprinkled)", std_remove);
-
- // ranges::remove
- bm_prefix<std::vector<int>>("ranges::remove(vector<int>) (prefix)", ranges_remove);
- bm_sprinkled<std::vector<int>>("ranges::remove(vector<int>) (sprinkled)", ranges_remove);
-
- bm_prefix<std::deque<int>>("ranges::remove(deque<int>) (prefix)", ranges_remove);
- bm_sprinkled<std::deque<int>>("ranges::remove(deque<int>) (sprinkled)", ranges_remove);
-
- bm_prefix<std::list<int>>("ranges::remove(list<int>) (prefix)", ranges_remove);
- bm_sprinkled<std::list<int>>("ranges::remove(list<int>) (sprinkled)", ranges_remove);
+ auto std_remove = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
+
+ // Benchmark {std,ranges}::remove on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+ // where we remove the prefix of x's from the sequence.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto remove) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove(c[i].begin(), c[i].end(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::remove(vector<int>) (prefix)", std_remove);
+ bm.operator()<std::deque<int>>("std::remove(deque<int>) (prefix)", std_remove);
+ bm.operator()<std::list<int>>("std::remove(list<int>) (prefix)", std_remove);
+ bm.operator()<std::vector<int>>("rng::remove(vector<int>) (prefix)", std::ranges::remove);
+ bm.operator()<std::deque<int>>("rng::remove(deque<int>) (prefix)", std::ranges::remove);
+ bm.operator()<std::list<int>>("rng::remove(list<int>) (prefix)", std::ranges::remove);
+ }
+
+ // Benchmark {std,ranges}::remove on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+ // where we remove the x's from the sequence.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto remove) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; ++i) {
+ *out++ = (i % 2 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove(c[i].begin(), c[i].end(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::remove(vector<int>) (sprinkled)", std_remove);
+ bm.operator()<std::deque<int>>("std::remove(deque<int>) (sprinkled)", std_remove);
+ bm.operator()<std::list<int>>("std::remove(list<int>) (sprinkled)", std_remove);
+ bm.operator()<std::vector<int>>("rng::remove(vector<int>) (sprinkled)", std::ranges::remove);
+ bm.operator()<std::deque<int>>("rng::remove(deque<int>) (sprinkled)", std::ranges::remove);
+ bm.operator()<std::list<int>>("rng::remove(list<int>) (sprinkled)", std::ranges::remove);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
index 88c05384eb7bd..b5e876fc9ba15 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -19,88 +19,87 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove_copy) {
- auto bench = [remove_copy](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- std::fill_n(std::back_inserter(c), size / 2, x);
- std::fill_n(std::back_inserter(c), size / 2, y);
-
- std::vector<ValueType> out(size);
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove_copy) {
- auto bench = [remove_copy](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- for (std::size_t i = 0; i != size; ++i) {
- c.push_back(i % 2 == 0 ? x : y);
- }
-
- std::vector<ValueType> out(size);
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_remove_copy = [](auto first, auto last, auto out, auto const& value) {
return std::remove_copy(first, last, out, value);
};
- auto ranges_remove_copy = [](auto first, auto last, auto out, auto const& value) {
- return std::ranges::remove_copy(first, last, out, value);
- };
-
- // std::remove_copy
- bm_prefix<std::vector<int>>("std::remove_copy(vector<int>) (prefix)", std_remove_copy);
- bm_sprinkled<std::vector<int>>("std::remove_copy(vector<int>) (sprinkled)", std_remove_copy);
-
- bm_prefix<std::deque<int>>("std::remove_copy(deque<int>) (prefix)", std_remove_copy);
- bm_sprinkled<std::deque<int>>("std::remove_copy(deque<int>) (sprinkled)", std_remove_copy);
-
- bm_prefix<std::list<int>>("std::remove_copy(list<int>) (prefix)", std_remove_copy);
- bm_sprinkled<std::list<int>>("std::remove_copy(list<int>) (sprinkled)", std_remove_copy);
-
- // ranges::remove_copy
- bm_prefix<std::vector<int>>("ranges::remove_copy(vector<int>) (prefix)", ranges_remove_copy);
- bm_sprinkled<std::vector<int>>("ranges::remove_copy(vector<int>) (sprinkled)", ranges_remove_copy);
-
- bm_prefix<std::deque<int>>("ranges::remove_copy(deque<int>) (prefix)", ranges_remove_copy);
- bm_sprinkled<std::deque<int>>("ranges::remove_copy(deque<int>) (sprinkled)", ranges_remove_copy);
- bm_prefix<std::list<int>>("ranges::remove_copy(list<int>) (prefix)", ranges_remove_copy);
- bm_sprinkled<std::list<int>>("ranges::remove_copy(list<int>) (sprinkled)", ranges_remove_copy);
+ // Benchmark {std,ranges}::remove_copy on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+ // where we remove the prefix of x's from the sequence.
+ {
+ auto bm = []<class Container>(std::string name, auto remove_copy) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::remove_copy(vector<int>) (prefix)", std_remove_copy);
+ bm.operator()<std::deque<int>>("std::remove_copy(deque<int>) (prefix)", std_remove_copy);
+ bm.operator()<std::list<int>>("std::remove_copy(list<int>) (prefix)", std_remove_copy);
+ bm.operator()<std::vector<int>>("rng::remove_copy(vector<int>) (prefix)", std::ranges::remove_copy);
+ bm.operator()<std::deque<int>>("rng::remove_copy(deque<int>) (prefix)", std::ranges::remove_copy);
+ bm.operator()<std::list<int>>("rng::remove_copy(list<int>) (prefix)", std::ranges::remove_copy);
+ }
+
+ // Benchmark {std,ranges}::remove_copy on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+ // where we remove the x's from the sequence.
+ {
+ auto bm = []<class Container>(std::string name, auto remove_copy) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::remove_copy(vector<int>) (sprinkled)", std_remove_copy);
+ bm.operator()<std::deque<int>>("std::remove_copy(deque<int>) (sprinkled)", std_remove_copy);
+ bm.operator()<std::list<int>>("std::remove_copy(list<int>) (sprinkled)", std_remove_copy);
+ bm.operator()<std::vector<int>>("rng::remove_copy(vector<int>) (sprinkled)", std::ranges::remove_copy);
+ bm.operator()<std::deque<int>>("rng::remove_copy(deque<int>) (sprinkled)", std::ranges::remove_copy);
+ bm.operator()<std::list<int>>("rng::remove_copy(list<int>) (sprinkled)", std::ranges::remove_copy);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
index 95b0e93362bab..13464b65e8158 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -19,98 +19,97 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove_copy_if) {
- auto bench = [remove_copy_if](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- std::fill_n(std::back_inserter(c), size / 2, x);
- std::fill_n(std::back_inserter(c), size / 2, y);
-
- auto pred = [&](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
- };
-
- std::vector<ValueType> out(size);
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove_copy_if) {
- auto bench = [remove_copy_if](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- for (std::size_t i = 0; i != size; ++i) {
- c.push_back(i % 2 == 0 ? x : y);
- }
-
- auto pred = [&](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
- };
-
- std::vector<ValueType> out(size);
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
return std::remove_copy_if(first, last, out, pred);
};
- auto ranges_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
- return std::ranges::remove_copy_if(first, last, out, pred);
- };
-
- // std::remove_copy_if
- bm_prefix<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
- bm_sprinkled<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
-
- bm_prefix<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
- bm_sprinkled<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
- bm_prefix<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
- bm_sprinkled<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
-
- // ranges::remove_copy_if
- bm_prefix<std::vector<int>>("ranges::remove_copy_if(vector<int>) (prefix)", ranges_remove_copy_if);
- bm_sprinkled<std::vector<int>>("ranges::remove_copy_if(vector<int>) (sprinkled)", ranges_remove_copy_if);
-
- bm_prefix<std::deque<int>>("ranges::remove_copy_if(deque<int>) (prefix)", ranges_remove_copy_if);
- bm_sprinkled<std::deque<int>>("ranges::remove_copy_if(deque<int>) (sprinkled)", ranges_remove_copy_if);
-
- bm_prefix<std::list<int>>("ranges::remove_copy_if(list<int>) (prefix)", ranges_remove_copy_if);
- bm_sprinkled<std::list<int>>("ranges::remove_copy_if(list<int>) (sprinkled)", ranges_remove_copy_if);
+ // Benchmark {std,ranges}::remove_copy_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+ // where we remove the prefix of x's from the sequence.
+ {
+ auto bm = []<class Container>(std::string name, auto remove_copy_if) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove_copy_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
+ bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
+ bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
+ bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (prefix)", std::ranges::remove_copy_if);
+ bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (prefix)", std::ranges::remove_copy_if);
+ bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (prefix)", std::ranges::remove_copy_if);
+ }
+
+ // Benchmark {std,ranges}::remove_copy_if on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+ // where we remove the x's from the sequence.
+ {
+ auto bm = []<class Container>(std::string name, auto remove_copy_if) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove_copy_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
+ bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
+ bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
+ bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (sprinkled)", std::ranges::remove_copy_if);
+ bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (sprinkled)", std::ranges::remove_copy_if);
+ bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (sprinkled)", std::ranges::remove_copy_if);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
index db0dabfbaa2c3..9ccc436ba47cb 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -19,122 +19,123 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove_if) {
- auto bench = [remove_if](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
-
- auto pred = [&](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
- };
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = remove_if(c[i].begin(), c[i].end(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove_if) {
- auto bench = [remove_if](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto alternate = [&](auto out, auto n) {
- for (std::size_t i = 0; i != n; ++i) {
- *out++ = (i % 2 == 0 ? x : y);
- }
+int main(int argc, char** argv) {
+ auto std_remove_if = [](auto first, auto last, auto pred) { return std::remove_if(first, last, pred); };
+
+ // Benchmark {std,ranges}::remove_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+ // where we remove the prefix of x's from the sequence.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto remove_if) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove_if](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove_if(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
};
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- alternate(c[i].begin(), size);
- }
-
- auto pred = [&](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
+ bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
+ bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
+ bm.operator()<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
+ bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (prefix)", std::ranges::remove_if);
+ bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (prefix)", std::ranges::remove_if);
+ bm.operator()<std::list<int>>("rng::remove_if(list<int>) (prefix)", std::ranges::remove_if);
+ }
+
+ // Benchmark {std,ranges}::remove_if on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+ // where we remove the x's from the sequence.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto remove_if) {
+ benchmark::RegisterBenchmark(
+ name,
+ [remove_if](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; ++i) {
+ *out++ = (i % 2 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = remove_if(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::DoNotOptimize(x);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
};
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = remove_if(c[i].begin(), c[i].end(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- alternate(c[i].begin(), size);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-int main(int argc, char** argv) {
- auto std_remove_if = [](auto first, auto last, auto pred) { return std::remove_if(first, last, pred); };
- auto ranges_remove_if = [](auto first, auto last, auto pred) { return std::ranges::remove_if(first, last, pred); };
-
- // std::remove_if
- bm_prefix<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
- bm_sprinkled<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
-
- bm_prefix<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
- bm_sprinkled<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
-
- bm_prefix<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
- bm_sprinkled<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
-
- // ranges::remove_if
- bm_prefix<std::vector<int>>("ranges::remove_if(vector<int>) (prefix)", ranges_remove_if);
- bm_sprinkled<std::vector<int>>("ranges::remove_if(vector<int>) (sprinkled)", ranges_remove_if);
-
- bm_prefix<std::deque<int>>("ranges::remove_if(deque<int>) (prefix)", ranges_remove_if);
- bm_sprinkled<std::deque<int>>("ranges::remove_if(deque<int>) (sprinkled)", ranges_remove_if);
-
- bm_prefix<std::list<int>>("ranges::remove_if(list<int>) (prefix)", ranges_remove_if);
- bm_sprinkled<std::list<int>>("ranges::remove_if(list<int>) (sprinkled)", ranges_remove_if);
+ bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
+ bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
+ bm.operator()<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
+ bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (sprinkled)", std::ranges::remove_if);
+ bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (sprinkled)", std::ranges::remove_if);
+ bm.operator()<std::list<int>>("rng::remove_if(list<int>) (sprinkled)", std::ranges::remove_if);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
index b55790d4db017..48ab1063a9954 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -19,86 +19,85 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
-// into zzzzzzzzzzzyyyyyyyyyy and then back.
-//
-// This measures the performance of replace() when replacing a large
-// contiguous sequence of equal values.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation replace) {
- auto bench = [replace](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- ValueType z = Generate<ValueType>::random();
- std::fill_n(std::back_inserter(c), size / 2, x);
- std::fill_n(std::back_inserter(c), size / 2, y);
-
- for ([[maybe_unused]] auto _ : st) {
- replace(c.begin(), c.end(), x, z);
- std::swap(x, z);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation replace) {
- auto bench = [replace](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- ValueType z = Generate<ValueType>::random();
- for (std::size_t i = 0; i != size; ++i) {
- c.push_back(i % 2 == 0 ? x : y);
- }
-
- for ([[maybe_unused]] auto _ : st) {
- replace(c.begin(), c.end(), x, z);
- std::swap(x, z);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_replace = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
- auto ranges_replace = [](auto first, auto last, auto old, auto new_) {
- return std::ranges::replace(first, last, old, new_);
- };
-
- // std::replace
- bm_prefix<std::vector<int>>("std::replace(vector<int>) (prefix)", std_replace);
- bm_sprinkled<std::vector<int>>("std::replace(vector<int>) (sprinkled)", std_replace);
-
- bm_prefix<std::deque<int>>("std::replace(deque<int>) (prefix)", std_replace);
- bm_sprinkled<std::deque<int>>("std::replace(deque<int>) (sprinkled)", std_replace);
+ auto std_replace = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
- bm_prefix<std::list<int>>("std::replace(list<int>) (prefix)", std_replace);
- bm_sprinkled<std::list<int>>("std::replace(list<int>) (sprinkled)", std_replace);
+ // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
+ // into zzzzzzzzzzzyyyyyyyyyy and then back.
+ //
+ // This measures the performance of replace() when replacing a large
+ // contiguous sequence of equal values.
+ {
+ auto bm = []<class Container>(std::string name, auto replace) {
+ benchmark::RegisterBenchmark(
+ name,
+ [replace](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
- // ranges::replace
- bm_prefix<std::vector<int>>("ranges::replace(vector<int>) (prefix)", ranges_replace);
- bm_sprinkled<std::vector<int>>("ranges::replace(vector<int>) (sprinkled)", ranges_replace);
+ for ([[maybe_unused]] auto _ : st) {
+ replace(c.begin(), c.end(), x, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::replace(vector<int>) (prefix)", std_replace);
+ bm.operator()<std::deque<int>>("std::replace(deque<int>) (prefix)", std_replace);
+ bm.operator()<std::list<int>>("std::replace(list<int>) (prefix)", std_replace);
+ bm.operator()<std::vector<int>>("rng::replace(vector<int>) (prefix)", std::ranges::replace);
+ bm.operator()<std::deque<int>>("rng::replace(deque<int>) (prefix)", std::ranges::replace);
+ bm.operator()<std::list<int>>("rng::replace(list<int>) (prefix)", std::ranges::replace);
+ }
- bm_prefix<std::deque<int>>("ranges::replace(deque<int>) (prefix)", ranges_replace);
- bm_sprinkled<std::deque<int>>("ranges::replace(deque<int>) (sprinkled)", ranges_replace);
+ // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+ {
+ auto bm = []<class Container>(std::string name, auto replace) {
+ benchmark::RegisterBenchmark(
+ name,
+ [replace](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
- bm_prefix<std::list<int>>("ranges::replace(list<int>) (prefix)", ranges_replace);
- bm_sprinkled<std::list<int>>("ranges::replace(list<int>) (sprinkled)", ranges_replace);
+ for ([[maybe_unused]] auto _ : st) {
+ replace(c.begin(), c.end(), x, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::replace(vector<int>) (sprinkled)", std_replace);
+ bm.operator()<std::deque<int>>("std::replace(deque<int>) (sprinkled)", std_replace);
+ bm.operator()<std::list<int>>("std::replace(list<int>) (sprinkled)", std_replace);
+ bm.operator()<std::vector<int>>("rng::replace(vector<int>) (sprinkled)", std::ranges::replace);
+ bm.operator()<std::deque<int>>("rng::replace(deque<int>) (sprinkled)", std::ranges::replace);
+ bm.operator()<std::list<int>>("rng::replace(list<int>) (sprinkled)", std::ranges::replace);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
index 820cf08e5a901..3b139c54eeb12 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -19,96 +19,95 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
-// into zzzzzzzzzzzyyyyyyyyyy and then back.
-//
-// This measures the performance of replace_if() when replacing a large
-// contiguous sequence of equal values.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation replace_if) {
- auto bench = [replace_if](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- ValueType z = Generate<ValueType>::random();
- std::fill_n(std::back_inserter(c), size / 2, x);
- std::fill_n(std::back_inserter(c), size / 2, y);
-
- for ([[maybe_unused]] auto _ : st) {
- auto pred = [&x](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
- };
- replace_if(c.begin(), c.end(), pred, z);
- std::swap(x, z);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation replace_if) {
- auto bench = [replace_if](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c;
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- ValueType z = Generate<ValueType>::random();
- for (std::size_t i = 0; i != size; ++i) {
- c.push_back(i % 2 == 0 ? x : y);
- }
-
- for ([[maybe_unused]] auto _ : st) {
- auto pred = [&x](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
- };
- replace_if(c.begin(), c.end(), pred, z);
- std::swap(x, z);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_replace_if = [](auto first, auto last, auto pred, auto new_) {
return std::replace_if(first, last, pred, new_);
};
- auto ranges_replace_if = [](auto first, auto last, auto pred, auto new_) {
- return std::ranges::replace_if(first, last, pred, new_);
- };
-
- // std::replace_if
- bm_prefix<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
- bm_sprinkled<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
-
- bm_prefix<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
- bm_sprinkled<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
- bm_prefix<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
- bm_sprinkled<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
+ // Benchmark {std,ranges}::replace_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+ // where we replace into zzzzzzzzzzzyyyyyyyyyy and then back.
+ //
+ // This measures the performance of replace_if() when replacing a large
+ // contiguous sequence of equal values.
+ {
+ auto bm = []<class Container>(std::string name, auto replace_if) {
+ benchmark::RegisterBenchmark(
+ name,
+ [replace_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ std::fill_n(std::back_inserter(c), size / 2, x);
+ std::fill_n(std::back_inserter(c), size / 2, y);
- // ranges::replace_if
- bm_prefix<std::vector<int>>("ranges::replace_if(vector<int>) (prefix)", ranges_replace_if);
- bm_sprinkled<std::vector<int>>("ranges::replace_if(vector<int>) (sprinkled)", ranges_replace_if);
+ for ([[maybe_unused]] auto _ : st) {
+ auto pred = [&x](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+ replace_if(c.begin(), c.end(), pred, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
+ bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
+ bm.operator()<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
+ bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (prefix)", std::ranges::replace_if);
+ bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (prefix)", std::ranges::replace_if);
+ bm.operator()<std::list<int>>("rng::replace_if(list<int>) (prefix)", std::ranges::replace_if);
+ }
- bm_prefix<std::deque<int>>("ranges::replace_if(deque<int>) (prefix)", ranges_replace_if);
- bm_sprinkled<std::deque<int>>("ranges::replace_if(deque<int>) (sprinkled)", ranges_replace_if);
+ // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+ {
+ auto bm = []<class Container>(std::string name, auto replace_if) {
+ benchmark::RegisterBenchmark(
+ name,
+ [replace_if](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c;
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ ValueType z = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != size; ++i) {
+ c.push_back(i % 2 == 0 ? x : y);
+ }
- bm_prefix<std::list<int>>("ranges::replace_if(list<int>) (prefix)", ranges_replace_if);
- bm_sprinkled<std::list<int>>("ranges::replace_if(list<int>) (sprinkled)", ranges_replace_if);
+ for ([[maybe_unused]] auto _ : st) {
+ auto pred = [&x](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+ replace_if(c.begin(), c.end(), pred, z);
+ std::swap(x, z);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(z);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
+ bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
+ bm.operator()<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
+ bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (sprinkled)", std::ranges::replace_if);
+ bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (sprinkled)", std::ranges::replace_if);
+ bm.operator()<std::list<int>>("rng::replace_if(list<int>) (sprinkled)", std::ranges::replace_if);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
index dbb0d43d091c3..4ce2133c9a557 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
@@ -19,36 +19,32 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation reverse) {
- auto bench = [reverse](auto& st) {
- std::size_t 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(); });
-
- for ([[maybe_unused]] auto _ : st) {
- reverse(c.begin(), c.end());
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
-}
-
int main(int argc, char** argv) {
- auto std_reverse = [](auto first, auto last) { return std::reverse(first, last); };
- auto ranges_reverse = [](auto first, auto last) { return std::ranges::reverse(first, last); };
-
- // std::reverse
- bm<std::vector<int>>("std::reverse(vector<int>)", std_reverse);
- bm<std::deque<int>>("std::reverse(deque<int>)", std_reverse);
- bm<std::list<int>>("std::reverse(list<int>)", std_reverse);
-
- // ranges::reverse
- bm<std::vector<int>>("ranges::reverse(vector<int>)", ranges_reverse);
- bm<std::deque<int>>("ranges::reverse(deque<int>)", ranges_reverse);
- bm<std::list<int>>("ranges::reverse(list<int>)", ranges_reverse);
+ auto std_reverse = [](auto first, auto last) { return std::reverse(first, last); };
+
+ // {std,ranges}::reverse(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto reverse) {
+ benchmark::RegisterBenchmark(name, [reverse](auto& st) {
+ std::size_t 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(); });
+
+ for ([[maybe_unused]] auto _ : st) {
+ reverse(c.begin(), c.end());
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })->Range(8, 1 << 15);
+ };
+ bm.operator()<std::vector<int>>("std::reverse(vector<int>)", std_reverse);
+ bm.operator()<std::deque<int>>("std::reverse(deque<int>)", std_reverse);
+ bm.operator()<std::list<int>>("std::reverse(list<int>)", std_reverse);
+ bm.operator()<std::vector<int>>("rng::reverse(vector<int>)", std::ranges::reverse);
+ bm.operator()<std::deque<int>>("rng::reverse(deque<int>)", std::ranges::reverse);
+ bm.operator()<std::list<int>>("rng::reverse(list<int>)", std::ranges::reverse);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
index 84322fbfff40c..c77cb9a560494 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
@@ -19,40 +19,34 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation reverse_copy) {
- auto bench = [reverse_copy](auto& st) {
- std::size_t 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) {
- reverse_copy(c.begin(), c.end(), out.begin());
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
-}
-
int main(int argc, char** argv) {
- auto std_reverse_copy = [](auto first, auto last, auto out) { return std::reverse_copy(first, last, out); };
- auto ranges_reverse_copy = [](auto first, auto last, auto out) {
- return std::ranges::reverse_copy(first, last, out);
- };
-
- // std::reverse_copy
- bm<std::vector<int>>("std::reverse_copy(vector<int>)", std_reverse_copy);
- bm<std::deque<int>>("std::reverse_copy(deque<int>)", std_reverse_copy);
- bm<std::list<int>>("std::reverse_copy(list<int>)", std_reverse_copy);
-
- // ranges::reverse_copy
- bm<std::vector<int>>("ranges::reverse_copy(vector<int>)", ranges_reverse_copy);
- bm<std::deque<int>>("ranges::reverse_copy(deque<int>)", ranges_reverse_copy);
- bm<std::list<int>>("ranges::reverse_copy(list<int>)", ranges_reverse_copy);
+ auto std_reverse_copy = [](auto first, auto last, auto out) { return std::reverse_copy(first, last, out); };
+
+ // {std,ranges}::reverse_copy(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto reverse_copy) {
+ benchmark::RegisterBenchmark(name, [reverse_copy](auto& st) {
+ std::size_t 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) {
+ reverse_copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })->Range(8, 1 << 15);
+ };
+ bm.operator()<std::vector<int>>("std::reverse_copy(vector<int>)", std_reverse_copy);
+ bm.operator()<std::deque<int>>("std::reverse_copy(deque<int>)", std_reverse_copy);
+ bm.operator()<std::list<int>>("std::reverse_copy(list<int>)", std_reverse_copy);
+ bm.operator()<std::vector<int>>("rng::reverse_copy(vector<int>)", std::ranges::reverse_copy);
+ bm.operator()<std::deque<int>>("rng::reverse_copy(deque<int>)", std::ranges::reverse_copy);
+ bm.operator()<std::list<int>>("rng::reverse_copy(list<int>)", std::ranges::reverse_copy);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
index eb91a011d863a..e32afbc87c9a0 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -19,38 +19,39 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation rotate) {
- auto bench = [rotate](auto& st) {
- std::size_t 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(); });
-
- auto middle = std::next(c.begin(), size / 2);
- for ([[maybe_unused]] auto _ : st) {
- auto result = rotate(c.begin(), middle, c.end());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_rotate = [](auto first, auto middle, auto last) { return std::rotate(first, middle, last); };
- auto ranges_rotate = [](auto first, auto middle, auto last) { return std::ranges::rotate(first, middle, last); };
-
- // std::rotate
- bm<std::vector<int>>("std::rotate(vector<int>)", std_rotate);
- bm<std::deque<int>>("std::rotate(deque<int>)", std_rotate);
- bm<std::list<int>>("std::rotate(list<int>)", std_rotate);
-
- // ranges::rotate
- bm<std::vector<int>>("ranges::rotate(vector<int>)", ranges_rotate);
- bm<std::deque<int>>("ranges::rotate(deque<int>)", ranges_rotate);
- bm<std::list<int>>("ranges::rotate(list<int>)", ranges_rotate);
+ auto std_rotate = [](auto first, auto middle, auto last) { return std::rotate(first, middle, last); };
+
+ // {std,ranges}::rotate(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto rotate) {
+ benchmark::RegisterBenchmark(
+ name,
+ [rotate](auto& st) {
+ std::size_t 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(); });
+
+ auto middle = std::next(c.begin(), size / 2);
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = rotate(c.begin(), middle, c.end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::rotate(vector<int>)", std_rotate);
+ bm.operator()<std::deque<int>>("std::rotate(deque<int>)", std_rotate);
+ bm.operator()<std::list<int>>("std::rotate(list<int>)", std_rotate);
+ bm.operator()<std::vector<int>>("rng::rotate(vector<int>)", std::ranges::rotate);
+ bm.operator()<std::deque<int>>("rng::rotate(deque<int>)", std::ranges::rotate);
+ bm.operator()<std::list<int>>("rng::rotate(list<int>)", std::ranges::rotate);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
index f5c14640fa87d..7972f1aba096e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
@@ -19,44 +19,43 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation rotate_copy) {
- auto bench = [rotate_copy](auto& st) {
- std::size_t 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);
-
- auto middle = std::next(c.begin(), size / 2);
- for ([[maybe_unused]] auto _ : st) {
- auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_rotate_copy = [](auto first, auto middle, auto last, auto out) {
return std::rotate_copy(first, middle, last, out);
};
- auto ranges_rotate_copy = [](auto first, auto middle, auto last, auto out) {
- return std::ranges::rotate_copy(first, middle, last, out);
- };
- // std::rotate_copy
- bm<std::vector<int>>("std::rotate_copy(vector<int>)", std_rotate_copy);
- bm<std::deque<int>>("std::rotate_copy(deque<int>)", std_rotate_copy);
- bm<std::list<int>>("std::rotate_copy(list<int>)", std_rotate_copy);
+ // {std,ranges}::rotate_copy(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto rotate_copy) {
+ benchmark::RegisterBenchmark(
+ name,
+ [rotate_copy](auto& st) {
+ std::size_t 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);
- // ranges::rotate_copy
- bm<std::vector<int>>("ranges::rotate_copy(vector<int>)", ranges_rotate_copy);
- bm<std::deque<int>>("ranges::rotate_copy(deque<int>)", ranges_rotate_copy);
- bm<std::list<int>>("ranges::rotate_copy(list<int>)", ranges_rotate_copy);
+ auto middle = std::next(c.begin(), size / 2);
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::rotate_copy(vector<int>)", std_rotate_copy);
+ bm.operator()<std::deque<int>>("std::rotate_copy(deque<int>)", std_rotate_copy);
+ bm.operator()<std::list<int>>("std::rotate_copy(list<int>)", std_rotate_copy);
+ bm.operator()<std::vector<int>>("rng::rotate_copy(vector<int>)", std::ranges::rotate_copy);
+ bm.operator()<std::deque<int>>("rng::rotate_copy(deque<int>)", std::ranges::rotate_copy);
+ bm.operator()<std::list<int>>("rng::rotate_copy(list<int>)", std::ranges::rotate_copy);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
index 5f783efe8f627..87ab7517cb723 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
@@ -20,46 +20,45 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation sample) {
- auto bench = [sample](auto& st) {
- std::size_t 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);
- auto const n = size / 4; // sample 1/4 of the range
- std::mt19937 rng;
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(out);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
return std::sample(first, last, out, n, rng);
};
- auto ranges_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
- return std::ranges::sample(first, last, out, n, rng);
- };
- // std::sample
- bm<std::vector<int>>("std::sample(vector<int>)", std_sample);
- bm<std::deque<int>>("std::sample(deque<int>)", std_sample);
- bm<std::list<int>>("std::sample(list<int>)", std_sample);
+ // {std,ranges}::sample(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto sample) {
+ benchmark::RegisterBenchmark(
+ name,
+ [sample](auto& st) {
+ std::size_t 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);
+ auto const n = size / 4; // sample 1/4 of the range
+ std::mt19937 rng;
- // ranges::sample
- bm<std::vector<int>>("ranges::sample(vector<int>)", ranges_sample);
- bm<std::deque<int>>("ranges::sample(deque<int>)", ranges_sample);
- bm<std::list<int>>("ranges::sample(list<int>)", ranges_sample);
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::sample(vector<int>)", std_sample);
+ bm.operator()<std::deque<int>>("std::sample(deque<int>)", std_sample);
+ bm.operator()<std::list<int>>("std::sample(list<int>)", std_sample);
+ bm.operator()<std::vector<int>>("rng::sample(vector<int>)", std::ranges::sample);
+ bm.operator()<std::deque<int>>("rng::sample(deque<int>)", std::ranges::sample);
+ bm.operator()<std::list<int>>("rng::sample(list<int>)", std::ranges::sample);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
index 9cf428f67e03e..24a3d34c65f09 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -19,35 +19,38 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation shift_left) {
- auto bench = [shift_left](auto& st) {
- std::size_t 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(); });
-
- auto const n = 9 * (size / 10); // shift all but 10% of the range
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = shift_left(c.begin(), c.end(), n);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_shift_left = [](auto first, auto last, auto n) { return std::shift_left(first, last, n); };
- // std::shift_left
- bm<std::vector<int>>("std::shift_left(vector<int>)", std_shift_left);
- bm<std::deque<int>>("std::shift_left(deque<int>)", std_shift_left);
- bm<std::list<int>>("std::shift_left(list<int>)", std_shift_left);
-
- // ranges::shift_left not implemented yet
+ // std::shift_left(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto shift_left) {
+ benchmark::RegisterBenchmark(
+ name,
+ [shift_left](auto& st) {
+ std::size_t 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(); });
+
+ auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = shift_left(c.begin(), c.end(), n);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::shift_left(vector<int>)", std_shift_left);
+ bm.operator()<std::deque<int>>("std::shift_left(deque<int>)", std_shift_left);
+ bm.operator()<std::list<int>>("std::shift_left(list<int>)", std_shift_left);
+ // ranges::shift_left not implemented yet
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
index 31a980ebdc5c1..90fb507643149 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -19,35 +19,38 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation shift_right) {
- auto bench = [shift_right](auto& st) {
- std::size_t 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(); });
-
- auto const n = 9 * (size / 10); // shift all but 10% of the range
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = shift_right(c.begin(), c.end(), n);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_shift_right = [](auto first, auto last, auto n) { return std::shift_right(first, last, n); };
- // std::shift_right
- bm<std::vector<int>>("std::shift_right(vector<int>)", std_shift_right);
- bm<std::deque<int>>("std::shift_right(deque<int>)", std_shift_right);
- bm<std::list<int>>("std::shift_right(list<int>)", std_shift_right);
-
- // ranges::shift_right not implemented yet
+ // std::shift_right(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto shift_right) {
+ benchmark::RegisterBenchmark(
+ name,
+ [shift_right](auto& st) {
+ std::size_t 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(); });
+
+ auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = shift_right(c.begin(), c.end(), n);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::shift_right(vector<int>)", std_shift_right);
+ bm.operator()<std::deque<int>>("std::shift_right(deque<int>)", std_shift_right);
+ bm.operator()<std::list<int>>("std::shift_right(list<int>)", std_shift_right);
+ // ranges::shift_right not implemented yet
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
index cc483b631c2a4..f50dff7635703 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
@@ -19,35 +19,36 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation shuffle) {
- auto bench = [shuffle](auto& st) {
- std::size_t 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::mt19937 rng;
-
- for ([[maybe_unused]] auto _ : st) {
- shuffle(c.begin(), c.end(), rng);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_shuffle = [](auto first, auto last, auto& rng) { return std::shuffle(first, last, rng); };
- auto ranges_shuffle = [](auto first, auto last, auto& rng) { return std::ranges::shuffle(first, last, rng); };
-
- // std::shuffle
- bm<std::vector<int>>("std::shuffle(vector<int>)", std_shuffle);
- bm<std::deque<int>>("std::shuffle(deque<int>)", std_shuffle);
-
- // ranges::shuffle
- bm<std::vector<int>>("ranges::shuffle(vector<int>)", ranges_shuffle);
- bm<std::deque<int>>("ranges::shuffle(deque<int>)", ranges_shuffle);
+ auto std_shuffle = [](auto first, auto last, auto& rng) { return std::shuffle(first, last, rng); };
+
+ // {std,ranges}::shuffle(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto shuffle) {
+ benchmark::RegisterBenchmark(
+ name,
+ [shuffle](auto& st) {
+ std::size_t 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::mt19937 rng;
+
+ for ([[maybe_unused]] auto _ : st) {
+ shuffle(c.begin(), c.end(), rng);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::shuffle(vector<int>)", std_shuffle);
+ bm.operator()<std::deque<int>>("std::shuffle(deque<int>)", std_shuffle);
+ bm.operator()<std::vector<int>>("rng::shuffle(vector<int>)", std::ranges::shuffle);
+ bm.operator()<std::deque<int>>("rng::shuffle(deque<int>)", std::ranges::shuffle);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
index 05b733fecc70d..f7c2ff1252b09 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
@@ -19,43 +19,42 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation swap_ranges) {
- auto bench = [swap_ranges](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c1, c2;
- std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
- std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c1);
- benchmark::DoNotOptimize(c2);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_swap_ranges = [](auto first1, auto last1, auto first2, auto) {
return std::swap_ranges(first1, last1, first2);
};
- auto ranges_swap_ranges = [](auto first1, auto last1, auto first2, auto last2) {
- return std::ranges::swap_ranges(first1, last1, first2, last2);
- };
-
- // std::swap_ranges
- bm<std::vector<int>>("std::swap_ranges(vector<int>)", std_swap_ranges);
- bm<std::deque<int>>("std::swap_ranges(deque<int>)", std_swap_ranges);
- bm<std::list<int>>("std::swap_ranges(list<int>)", std_swap_ranges);
- // ranges::swap_ranges
- bm<std::vector<int>>("ranges::swap_ranges(vector<int>)", ranges_swap_ranges);
- bm<std::deque<int>>("ranges::swap_ranges(deque<int>)", ranges_swap_ranges);
- bm<std::list<int>>("ranges::swap_ranges(list<int>)", ranges_swap_ranges);
+ // {std,ranges}::swap_ranges(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto swap_ranges) {
+ benchmark::RegisterBenchmark(
+ name,
+ [swap_ranges](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1, c2;
+ std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c1);
+ benchmark::DoNotOptimize(c2);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::swap_ranges(vector<int>)", std_swap_ranges);
+ bm.operator()<std::deque<int>>("std::swap_ranges(deque<int>)", std_swap_ranges);
+ bm.operator()<std::list<int>>("std::swap_ranges(list<int>)", std_swap_ranges);
+ bm.operator()<std::vector<int>>("rng::swap_ranges(vector<int>)", std::ranges::swap_ranges);
+ bm.operator()<std::deque<int>>("rng::swap_ranges(deque<int>)", std::ranges::swap_ranges);
+ bm.operator()<std::list<int>>("rng::swap_ranges(list<int>)", std::ranges::swap_ranges);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
index bdc913356d3c9..b3e1195bcecb8 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -19,52 +19,51 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation transform) {
- auto bench = [transform](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c1, c2;
- std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
- std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
-
- std::vector<ValueType> out(size);
-
- auto f = [](auto& x, auto& y) {
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- return x + y;
- };
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(c1);
- benchmark::DoNotOptimize(c2);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_transform = [](auto first1, auto last1, auto first2, auto, auto out, auto f) {
return std::transform(first1, last1, first2, out, f);
};
- auto ranges_transform = [](auto first1, auto last1, auto first2, auto last2, auto out, auto f) {
- return std::ranges::transform(first1, last1, first2, last2, out, f);
- };
- // std::transform
- bm<std::vector<int>>("std::transform(vector<int>, vector<int>)", std_transform);
- bm<std::deque<int>>("std::transform(deque<int>, deque<int>)", std_transform);
- bm<std::list<int>>("std::transform(list<int>, list<int>)", std_transform);
+ // {std,ranges}::transform(normal container, normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto transform) {
+ benchmark::RegisterBenchmark(
+ name,
+ [transform](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1, c2;
+ std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+ std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+ std::vector<ValueType> out(size);
- // ranges::transform
- bm<std::vector<int>>("ranges::transform(vector<int>, vector<int>)", ranges_transform);
- bm<std::deque<int>>("ranges::transform(deque<int>, deque<int>)", ranges_transform);
- bm<std::list<int>>("ranges::transform(list<int>, list<int>)", ranges_transform);
+ auto f = [](auto& x, auto& y) {
+ benchmark::DoNotOptimize(x);
+ benchmark::DoNotOptimize(y);
+ return x + y;
+ };
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c1);
+ benchmark::DoNotOptimize(c2);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::transform(vector<int>, vector<int>)", std_transform);
+ bm.operator()<std::deque<int>>("std::transform(deque<int>, deque<int>)", std_transform);
+ bm.operator()<std::list<int>>("std::transform(list<int>, list<int>)", std_transform);
+ bm.operator()<std::vector<int>>("rng::transform(vector<int>, vector<int>)", std::ranges::transform);
+ bm.operator()<std::deque<int>>("rng::transform(deque<int>, deque<int>)", std::ranges::transform);
+ bm.operator()<std::list<int>>("rng::transform(list<int>, list<int>)", std::ranges::transform);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
index 6cf56368f63f3..837be87ada70b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -19,47 +19,46 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation transform) {
- auto bench = [transform](auto& st) {
- std::size_t 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(); });
+int main(int argc, char** argv) {
+ auto std_transform = [](auto first, auto last, auto out, auto f) { return std::transform(first, last, out, f); };
- std::vector<ValueType> out(size);
+ // {std,ranges}::transform(normal container)
+ {
+ auto bm = []<class Container>(std::string name, auto transform) {
+ benchmark::RegisterBenchmark(
+ name,
+ [transform](auto& st) {
+ std::size_t 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(); });
- auto f = [](auto& element) {
- benchmark::DoNotOptimize(element);
- return element;
- };
+ std::vector<ValueType> out(size);
- for ([[maybe_unused]] auto _ : st) {
- auto result = transform(c.begin(), c.end(), out.begin(), f);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
+ auto f = [](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element;
+ };
-int main(int argc, char** argv) {
- auto std_transform = [](auto first, auto last, auto out, auto f) { return std::transform(first, last, out, f); };
- auto ranges_transform = [](auto first, auto last, auto out, auto f) {
- return std::ranges::transform(first, last, out, f);
- };
-
- // std::transform
- bm<std::vector<int>>("std::transform(vector<int>) (identity transform)", std_transform);
- bm<std::deque<int>>("std::transform(deque<int>) (identity transform)", std_transform);
- bm<std::list<int>>("std::transform(list<int>) (identity transform)", std_transform);
-
- // ranges::transform
- bm<std::vector<int>>("ranges::transform(vector<int>) (identity transform)", ranges_transform);
- bm<std::deque<int>>("ranges::transform(deque<int>) (identity transform)", ranges_transform);
- bm<std::list<int>>("ranges::transform(list<int>) (identity transform)", ranges_transform);
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = transform(c.begin(), c.end(), out.begin(), f);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(out);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::transform(vector<int>) (identity transform)", std_transform);
+ bm.operator()<std::deque<int>>("std::transform(deque<int>) (identity transform)", std_transform);
+ bm.operator()<std::list<int>>("std::transform(list<int>) (identity transform)", std_transform);
+ bm.operator()<std::vector<int>>("rng::transform(vector<int>) (identity transform)", std::ranges::transform);
+ bm.operator()<std::deque<int>>("rng::transform(deque<int>) (identity transform)", std::ranges::transform);
+ bm.operator()<std::list<int>>("rng::transform(list<int>) (identity transform)", std::ranges::transform);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index 1d9cca2f60688..8cc80982de70b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -19,111 +19,112 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique) {
- auto bench = [unique](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = unique(c[i].begin(), c[i].end());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique) {
- auto bench = [unique](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto alternate = [&](auto out, auto n) {
- for (std::size_t i = 0; i != n; i += 2) {
- *out++ = (i % 4 == 0 ? x : y);
- *out++ = (i % 4 == 0 ? x : y);
- }
- };
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- alternate(c[i].begin(), size);
- }
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = unique(c[i].begin(), c[i].end());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- alternate(c[i].begin(), size);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_unique = [](auto first, auto last) { return std::unique(first, last); };
- auto ranges_unique = [](auto first, auto last) { return std::ranges::unique(first, last); };
-
- // std::unique
- bm_contiguous<std::vector<int>>("std::unique(vector<int>) (contiguous)", std_unique);
- bm_sprinkled<std::vector<int>>("std::unique(vector<int>) (sprinkled)", std_unique);
-
- bm_contiguous<std::deque<int>>("std::unique(deque<int>) (contiguous)", std_unique);
- bm_sprinkled<std::deque<int>>("std::unique(deque<int>) (sprinkled)", std_unique);
-
- bm_contiguous<std::list<int>>("std::unique(list<int>) (contiguous)", std_unique);
- bm_sprinkled<std::list<int>>("std::unique(list<int>) (sprinkled)", std_unique);
-
- // ranges::unique
- bm_contiguous<std::vector<int>>("ranges::unique(vector<int>) (contiguous)", ranges_unique);
- bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>) (sprinkled)", ranges_unique);
-
- bm_contiguous<std::deque<int>>("ranges::unique(deque<int>) (contiguous)", ranges_unique);
- bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>) (sprinkled)", ranges_unique);
-
- bm_contiguous<std::list<int>>("ranges::unique(list<int>) (contiguous)", ranges_unique);
- bm_sprinkled<std::list<int>>("ranges::unique(list<int>) (sprinkled)", ranges_unique);
+ auto std_unique = [](auto first, auto last) { return std::unique(first, last); };
+
+ // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+ // adjacent equal elements.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto unique) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::unique(vector<int>) (contiguous)", std_unique);
+ bm.operator()<std::deque<int>>("std::unique(deque<int>) (contiguous)", std_unique);
+ bm.operator()<std::list<int>>("std::unique(list<int>) (contiguous)", std_unique);
+ bm.operator()<std::vector<int>>("rng::unique(vector<int>) (contiguous)", std::ranges::unique);
+ bm.operator()<std::deque<int>>("rng::unique(deque<int>) (contiguous)", std::ranges::unique);
+ bm.operator()<std::list<int>>("rng::unique(list<int>) (contiguous)", std::ranges::unique);
+ }
+
+ // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+ // adjacent equal elements.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto unique) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::unique(vector<int>) (sprinkled)", std_unique);
+ bm.operator()<std::deque<int>>("std::unique(deque<int>) (sprinkled)", std_unique);
+ bm.operator()<std::list<int>>("std::unique(list<int>) (sprinkled)", std_unique);
+ bm.operator()<std::vector<int>>("rng::unique(vector<int>) (sprinkled)", std::ranges::unique);
+ bm.operator()<std::deque<int>>("rng::unique(deque<int>) (sprinkled)", std::ranges::unique);
+ bm.operator()<std::list<int>>("rng::unique(list<int>) (sprinkled)", std::ranges::unique);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index c7b217ffd960d..3027953513958 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -19,84 +19,85 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique_copy) {
- auto bench = [unique_copy](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c(size);
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto half = size / 2;
- std::fill_n(std::fill_n(c.begin(), half, x), half, y);
-
- std::vector<ValueType> out(size);
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = unique_copy(c.begin(), c.end(), out.begin());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique_copy) {
- auto bench = [unique_copy](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c(size);
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto alternate = [&](auto out, auto n) {
- for (std::size_t i = 0; i != n; i += 2) {
- *out++ = (i % 4 == 0 ? x : y);
- *out++ = (i % 4 == 0 ? x : y);
- }
- };
- alternate(c.begin(), size);
-
- std::vector<ValueType> out(size);
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = unique_copy(c.begin(), c.end(), out.begin());
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
- auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
- auto ranges_unique_copy = [](auto first, auto last, auto out) { return std::ranges::unique_copy(first, last, out); };
-
- // std::unique_copy
- bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);
- bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);
-
- bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);
- bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);
-
- bm_contiguous<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);
- bm_sprinkled<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);
-
- // ranges::unique_copy
- bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>) (contiguous)", ranges_unique_copy);
- bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>) (sprinkled)", ranges_unique_copy);
-
- bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>) (contiguous)", ranges_unique_copy);
- bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>) (sprinkled)", ranges_unique_copy);
-
- bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>) (contiguous)", ranges_unique_copy);
- bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>) (sprinkled)", ranges_unique_copy);
+ auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
+
+ // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+ // adjacent equal elements.
+ {
+ auto bm = []<class Container>(std::string name, auto unique_copy) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);
+ bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);
+ bm.operator()<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);
+ bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (contiguous)", std::ranges::unique_copy);
+ bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (contiguous)", std::ranges::unique_copy);
+ bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (contiguous)", std::ranges::unique_copy);
+ }
+
+ // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+ // adjacent equal elements.
+ {
+ auto bm = []<class Container>(std::string name, auto unique_copy) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ alternate(c.begin(), size);
+
+ std::vector<ValueType> out(size);
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);
+ bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);
+ bm.operator()<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);
+ bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (sprinkled)", std::ranges::unique_copy);
+ bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (sprinkled)", std::ranges::unique_copy);
+ bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (sprinkled)", std::ranges::unique_copy);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
index 24ca442fb3de4..742feb873b25e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -19,100 +19,99 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique_copy) {
- auto bench = [unique_copy](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c(size);
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto half = size / 2;
- std::fill_n(std::fill_n(c.begin(), half, x), half, y);
-
- std::vector<ValueType> out(size);
-
- auto pred = [](auto& a, auto& b) {
- benchmark::DoNotOptimize(a);
- benchmark::DoNotOptimize(b);
- return a == b;
- };
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique_copy) {
- auto bench = [unique_copy](auto& st) {
- std::size_t const size = st.range(0);
- using ValueType = typename Container::value_type;
- Container c(size);
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto alternate = [&](auto out, auto n) {
- for (std::size_t i = 0; i != n; i += 2) {
- *out++ = (i % 4 == 0 ? x : y);
- *out++ = (i % 4 == 0 ? x : y);
- }
- };
- alternate(c.begin(), size);
-
- std::vector<ValueType> out(size);
-
- auto pred = [](auto& a, auto& b) {
- benchmark::DoNotOptimize(a);
- benchmark::DoNotOptimize(b);
- return a == b;
- };
-
- for ([[maybe_unused]] auto _ : st) {
- auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
int main(int argc, char** argv) {
auto std_unique_copy = [](auto first, auto last, auto out, auto pred) {
return std::unique_copy(first, last, out, pred);
};
- auto ranges_unique_copy = [](auto first, auto last, auto out, auto pred) {
- return std::ranges::unique_copy(first, last, out, pred);
- };
-
- // std::unique_copy
- bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy);
- bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy);
-
- bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy);
- bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy);
- bm_contiguous<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy);
- bm_sprinkled<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy);
-
- // ranges::unique_copy
- bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (contiguous)", ranges_unique_copy);
- bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (sprinkled)", ranges_unique_copy);
-
- bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (contiguous)", ranges_unique_copy);
- bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (sprinkled)", ranges_unique_copy);
-
- bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>, pred) (contiguous)", ranges_unique_copy);
- bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>, pred) (sprinkled)", ranges_unique_copy);
+ // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+ // adjacent equal elements.
+ {
+ auto bm = []<class Container>(std::string name, auto unique_copy) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+ std::vector<ValueType> out(size);
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy);
+ bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy);
+ bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy);
+ bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (contiguous)", std::ranges::unique_copy);
+ bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (contiguous)", std::ranges::unique_copy);
+ bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (contiguous)", std::ranges::unique_copy);
+ }
+
+ // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+ // adjacent equal elements.
+ {
+ auto bm = []<class Container>(std::string name, auto unique_copy) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique_copy](auto& st) {
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c(size);
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ alternate(c.begin(), size);
+
+ std::vector<ValueType> out(size);
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ for ([[maybe_unused]] auto _ : st) {
+ auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c);
+ benchmark::ClobberMemory();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
+ };
+ bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy);
+ bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy);
+ bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy);
+ bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (sprinkled)", std::ranges::unique_copy);
+ bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (sprinkled)", std::ranges::unique_copy);
+ bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (sprinkled)", std::ranges::unique_copy);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
index 0b258ea5cbecc..fb11f2e1adb9d 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -19,123 +19,124 @@
#include "benchmark/benchmark.h"
#include "../../GenerateInput.h"
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique) {
- auto bench = [unique](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
-
- auto pred = [](auto& a, auto& b) {
- benchmark::DoNotOptimize(a);
- benchmark::DoNotOptimize(b);
- return a == b;
- };
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = unique(c[i].begin(), c[i].end(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto half = size / 2;
- std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique) {
- auto bench = [unique](auto& st) {
- std::size_t const size = st.range(0);
- constexpr std::size_t BatchSize = 10;
- using ValueType = typename Container::value_type;
- Container c[BatchSize];
- ValueType x = Generate<ValueType>::random();
- ValueType y = Generate<ValueType>::random();
- auto alternate = [&](auto out, auto n) {
- for (std::size_t i = 0; i != n; i += 2) {
- *out++ = (i % 4 == 0 ? x : y);
- *out++ = (i % 4 == 0 ? x : y);
- }
+int main(int argc, char** argv) {
+ auto std_unique = [](auto first, auto last, auto pred) { return std::unique(first, last, pred); };
+
+ // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+ // adjacent equal elements.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto unique) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto half = size / 2;
+ std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
};
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = Container(size);
- alternate(c[i].begin(), size);
- }
-
- auto pred = [](auto& a, auto& b) {
- benchmark::DoNotOptimize(a);
- benchmark::DoNotOptimize(b);
- return a == b;
+ bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique);
+ bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique);
+ bm.operator()<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique);
+ bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (contiguous)", std::ranges::unique);
+ bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (contiguous)", std::ranges::unique);
+ bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (contiguous)", std::ranges::unique);
+ }
+
+ // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+ // adjacent equal elements.
+ //
+ // We perform this benchmark in a batch because we need to restore the
+ // state of the container after the operation.
+ {
+ auto bm = []<class Container>(std::string name, auto unique) {
+ benchmark::RegisterBenchmark(
+ name,
+ [unique](auto& st) {
+ std::size_t const size = st.range(0);
+ constexpr std::size_t BatchSize = 10;
+ using ValueType = typename Container::value_type;
+ Container c[BatchSize];
+ ValueType x = Generate<ValueType>::random();
+ ValueType y = Generate<ValueType>::random();
+ auto alternate = [&](auto out, auto n) {
+ for (std::size_t i = 0; i != n; i += 2) {
+ *out++ = (i % 4 == 0 ? x : y);
+ *out++ = (i % 4 == 0 ? x : y);
+ }
+ };
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i] = Container(size);
+ alternate(c[i].begin(), size);
+ }
+
+ auto pred = [](auto& a, auto& b) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ return a == b;
+ };
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = unique(c[i].begin(), c[i].end(), pred);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ alternate(c[i].begin(), size);
+ }
+ st.ResumeTiming();
+ }
+ })
+ ->Arg(32)
+ ->Arg(1024)
+ ->Arg(8192);
};
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = unique(c[i].begin(), c[i].end(), pred);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- alternate(c[i].begin(), size);
- }
- st.ResumeTiming();
- }
- };
- benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-int main(int argc, char** argv) {
- auto std_unique = [](auto first, auto last, auto pred) { return std::unique(first, last, pred); };
- auto ranges_unique = [](auto first, auto last, auto pred) { return std::ranges::unique(first, last, pred); };
-
- // std::unique
- bm_contiguous<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique);
- bm_sprinkled<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique);
-
- bm_contiguous<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique);
- bm_sprinkled<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique);
-
- bm_contiguous<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique);
- bm_sprinkled<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique);
-
- // ranges::unique
- bm_contiguous<std::vector<int>>("ranges::unique(vector<int>, pred) (contiguous)", ranges_unique);
- bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>, pred) (sprinkled)", ranges_unique);
-
- bm_contiguous<std::deque<int>>("ranges::unique(deque<int>, pred) (contiguous)", ranges_unique);
- bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>, pred) (sprinkled)", ranges_unique);
-
- bm_contiguous<std::list<int>>("ranges::unique(list<int>, pred) (contiguous)", ranges_unique);
- bm_sprinkled<std::list<int>>("ranges::unique(list<int>, pred) (sprinkled)", ranges_unique);
+ bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique);
+ bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique);
+ bm.operator()<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique);
+ bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (sprinkled)", std::ranges::unique);
+ bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (sprinkled)", std::ranges::unique);
+ bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (sprinkled)", std::ranges::unique);
+ }
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
>From 55c1ebe59fa435b33dac84a11a735c77e443bcc3 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 16:36:59 -0500
Subject: [PATCH 4/4] Fix DoNotOptimize
---
.../algorithms/modifying/fill.bench.cpp | 14 ++++-----
.../algorithms/modifying/fill_n.bench.cpp | 14 ++++-----
.../algorithms/modifying/generate.bench.cpp | 9 +++---
.../algorithms/modifying/generate_n.bench.cpp | 9 +++---
.../algorithms/modifying/move.bench.cpp | 31 ++++++++-----------
.../modifying/move_backward.bench.cpp | 31 ++++++++-----------
.../algorithms/modifying/remove.bench.cpp | 10 +++---
.../modifying/remove_copy.bench.cpp | 10 +++---
.../modifying/remove_copy_if.bench.cpp | 30 +++++++-----------
.../algorithms/modifying/remove_if.bench.cpp | 8 ++---
.../algorithms/modifying/replace.bench.cpp | 12 +++----
.../algorithms/modifying/replace_if.bench.cpp | 14 ++++-----
.../algorithms/modifying/reverse.bench.cpp | 2 +-
.../modifying/reverse_copy.bench.cpp | 5 +--
.../algorithms/modifying/rotate.bench.cpp | 3 +-
.../modifying/rotate_copy.bench.cpp | 4 +--
.../algorithms/modifying/sample.bench.cpp | 5 ++-
.../algorithms/modifying/shift_left.bench.cpp | 3 +-
.../modifying/shift_right.bench.cpp | 3 +-
.../algorithms/modifying/shuffle.bench.cpp | 2 +-
.../modifying/swap_ranges.bench.cpp | 3 +-
.../modifying/transform.binary.bench.cpp | 7 ++---
.../modifying/transform.unary.bench.cpp | 5 ++-
.../algorithms/modifying/unique.bench.cpp | 6 ++--
.../modifying/unique_copy.bench.cpp | 8 ++---
.../modifying/unique_copy_pred.bench.cpp | 8 ++---
.../modifying/unique_pred.bench.cpp | 6 ++--
27 files changed, 113 insertions(+), 149 deletions(-)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
index fb0fa8ffc5c69..79f6619e2977f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
@@ -36,12 +36,11 @@ int main(int argc, char** argv) {
Container c(size, y);
for ([[maybe_unused]] auto _ : st) {
- fill(c.begin(), c.end(), x);
- std::swap(x, y);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
+ fill(c.begin(), c.end(), x);
+ benchmark::DoNotOptimize(c);
+ std::swap(x, y);
}
})
->Arg(32)
@@ -66,12 +65,11 @@ int main(int argc, char** argv) {
std::vector<bool> c(size, y);
for ([[maybe_unused]] auto _ : st) {
- fill(c.begin(), c.end(), x);
- std::swap(x, y);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
+ fill(c.begin(), c.end(), x);
+ benchmark::DoNotOptimize(c);
+ std::swap(x, y);
}
})->Range(64, 1 << 20);
};
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
index d4ca98e623871..505fbcbb2f442 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
@@ -36,12 +36,11 @@ int main(int argc, char** argv) {
Container c(size, y);
for ([[maybe_unused]] auto _ : st) {
- fill_n(c.begin(), size, x);
- std::swap(x, y);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
+ fill_n(c.begin(), size, x);
+ benchmark::DoNotOptimize(c);
+ std::swap(x, y);
}
})
->Arg(32)
@@ -66,12 +65,11 @@ int main(int argc, char** argv) {
std::vector<bool> c(size, y);
for ([[maybe_unused]] auto _ : st) {
- fill_n(c.begin(), size, x);
- std::swap(x, y);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(y);
- benchmark::ClobberMemory();
+ fill_n(c.begin(), size, x);
+ benchmark::DoNotOptimize(c);
+ std::swap(x, y);
}
})->Range(64, 1 << 20);
};
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
index 9056d598d5d38..e3a8d650b5159 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
@@ -34,11 +34,12 @@ int main(int argc, char** argv) {
ValueType x = Generate<ValueType>::random();
for ([[maybe_unused]] auto _ : st) {
- auto f = [&x] { return x; };
- generate(c.begin(), c.end(), f);
benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ generate(c.begin(), c.end(), [&x] {
+ benchmark::DoNotOptimize(x);
+ return x;
+ });
+ benchmark::DoNotOptimize(c);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
index d33d9183dcb42..3671b66b21a85 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
@@ -34,11 +34,12 @@ int main(int argc, char** argv) {
ValueType x = Generate<ValueType>::random();
for ([[maybe_unused]] auto _ : st) {
- auto f = [&x] { return x; };
- generate_n(c.begin(), size, f);
benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ generate_n(c.begin(), size, [&x] {
+ benchmark::DoNotOptimize(x);
+ return x;
+ });
+ benchmark::DoNotOptimize(c);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
index f009850dac215..73e1a3881515f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
@@ -27,16 +27,16 @@ int main(int argc, char** argv) {
{
auto bm = []<class Container>(std::string name, auto move) {
benchmark::RegisterBenchmark(name, [move](auto& st) {
- std::size_t const n = st.range(0);
- using ValueType = typename Container::value_type;
- Container c1(n), c2(n);
- std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1(size), c2(size);
+ std::generate_n(c1.begin(), size, [] { return Generate<ValueType>::random(); });
Container* in = &c1;
Container* out = &c2;
for ([[maybe_unused]] auto _ : st) {
- benchmark::DoNotOptimize(c1);
- benchmark::DoNotOptimize(c2);
+ benchmark::DoNotOptimize(in);
+ benchmark::DoNotOptimize(out);
auto result = move(in->begin(), in->end(), out->begin());
benchmark::DoNotOptimize(result);
std::swap(in, out);
@@ -55,24 +55,19 @@ int main(int argc, char** argv) {
{
auto bm = []<bool Aligned>(std::string name, auto move) {
benchmark::RegisterBenchmark(name, [move](auto& st) {
- std::size_t const n = st.range(0);
- std::vector<bool> c1(n, true);
- std::vector<bool> c2(n, false);
+ std::size_t const size = st.range(0);
+ std::vector<bool> c1(size, true);
+ std::vector<bool> c2(size, false);
std::vector<bool>* in = &c1;
std::vector<bool>* out = &c2;
for (auto _ : st) {
- auto first1 = in->begin();
- auto last1 = in->end();
- auto first2 = out->begin();
- if constexpr (Aligned) {
- benchmark::DoNotOptimize(move(first1, last1, first2));
- } else {
- benchmark::DoNotOptimize(move(first1 + 4, last1, first2));
- }
- std::swap(in, out);
benchmark::DoNotOptimize(in);
benchmark::DoNotOptimize(out);
+ auto first = Aligned ? in->begin() : in->begin() + 4;
+ auto result = move(first, in->end(), out->begin());
+ benchmark::DoNotOptimize(result);
+ std::swap(in, out);
}
})->Range(64, 1 << 20);
};
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
index ef9373cbcdd72..0e6eea1b4d873 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
@@ -27,16 +27,16 @@ int main(int argc, char** argv) {
{
auto bm = []<class Container>(std::string name, auto move_backward) {
benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
- std::size_t const n = st.range(0);
- using ValueType = typename Container::value_type;
- Container c1(n), c2(n);
- std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+ std::size_t const size = st.range(0);
+ using ValueType = typename Container::value_type;
+ Container c1(size), c2(size);
+ std::generate_n(c1.begin(), size, [] { return Generate<ValueType>::random(); });
Container* in = &c1;
Container* out = &c2;
for ([[maybe_unused]] auto _ : st) {
- benchmark::DoNotOptimize(c1);
- benchmark::DoNotOptimize(c2);
+ benchmark::DoNotOptimize(in);
+ benchmark::DoNotOptimize(out);
auto result = move_backward(in->begin(), in->end(), out->end());
benchmark::DoNotOptimize(result);
std::swap(in, out);
@@ -55,24 +55,19 @@ int main(int argc, char** argv) {
{
auto bm = []<bool Aligned>(std::string name, auto move_backward) {
benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
- std::size_t const n = st.range(0);
- std::vector<bool> c1(n, true);
- std::vector<bool> c2(n, false);
+ std::size_t const size = st.range(0);
+ std::vector<bool> c1(size, true);
+ std::vector<bool> c2(size, false);
std::vector<bool>* in = &c1;
std::vector<bool>* out = &c2;
for (auto _ : st) {
- auto first1 = in->begin();
- auto last1 = in->end();
- auto last2 = out->end();
- if constexpr (Aligned) {
- benchmark::DoNotOptimize(move_backward(first1, last1, last2));
- } else {
- benchmark::DoNotOptimize(move_backward(first1, last1 - 4, last2));
- }
- std::swap(in, out);
benchmark::DoNotOptimize(in);
benchmark::DoNotOptimize(out);
+ auto last = Aligned ? in->end() : in->end() - 4;
+ auto result = move_backward(in->begin(), last, out->end());
+ benchmark::DoNotOptimize(result);
+ std::swap(in, out);
}
})->Range(64, 1 << 20);
};
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index 956753de13edc..adec1d2292bcf 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -46,11 +46,10 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = remove(c[i].begin(), c[i].end(), x);
- benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c[i]);
benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ auto result = remove(c[i].begin(), c[i].end(), x);
+ benchmark::DoNotOptimize(result);
}
st.PauseTiming();
@@ -101,11 +100,10 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
- auto result = remove(c[i].begin(), c[i].end(), x);
- benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c[i]);
benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ auto result = remove(c[i].begin(), c[i].end(), x);
+ benchmark::DoNotOptimize(result);
}
st.PauseTiming();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
index b5e876fc9ba15..af9994c07cc22 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -42,12 +42,11 @@ int main(int argc, char** argv) {
std::vector<ValueType> out(size);
for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
- benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(out);
benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+ benchmark::DoNotOptimize(result);
}
})
->Arg(32)
@@ -81,12 +80,11 @@ int main(int argc, char** argv) {
std::vector<ValueType> out(size);
for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
- benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(out);
benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+ benchmark::DoNotOptimize(result);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
index 13464b65e8158..e6fa7a0c1ea79 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -39,20 +39,17 @@ int main(int argc, char** argv) {
std::fill_n(std::back_inserter(c), size / 2, x);
std::fill_n(std::back_inserter(c), size / 2, y);
- auto pred = [&](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
- };
-
std::vector<ValueType> out(size);
for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
- benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ auto pred = [&x](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+ auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
}
})
->Arg(32)
@@ -83,20 +80,17 @@ int main(int argc, char** argv) {
c.push_back(i % 2 == 0 ? x : y);
}
- auto pred = [&](auto& element) {
- benchmark::DoNotOptimize(element);
- return element == x;
- };
-
std::vector<ValueType> out(size);
for ([[maybe_unused]] auto _ : st) {
- auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
- benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
+ auto pred = [&](auto& element) {
+ benchmark::DoNotOptimize(element);
+ return element == x;
+ };
+ auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+ benchmark::DoNotOptimize(result);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
index 9ccc436ba47cb..d5e185ef3ba9c 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -51,11 +51,9 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
+ benchmark::DoNotOptimize(c[i]);
auto result = remove_if(c[i].begin(), c[i].end(), pred);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
}
st.PauseTiming();
@@ -111,11 +109,9 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
+ benchmark::DoNotOptimize(c[i]);
auto result = remove_if(c[i].begin(), c[i].end(), pred);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::DoNotOptimize(x);
- benchmark::ClobberMemory();
}
st.PauseTiming();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
index 48ab1063a9954..e34f1e28c1459 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -42,12 +42,12 @@ int main(int argc, char** argv) {
std::fill_n(std::back_inserter(c), size / 2, y);
for ([[maybe_unused]] auto _ : st) {
- replace(c.begin(), c.end(), x, z);
- std::swap(x, z);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(x);
benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
+ replace(c.begin(), c.end(), x, z);
+ benchmark::DoNotOptimize(c);
+ std::swap(x, z);
}
})
->Arg(32)
@@ -79,12 +79,12 @@ int main(int argc, char** argv) {
}
for ([[maybe_unused]] auto _ : st) {
- replace(c.begin(), c.end(), x, z);
- std::swap(x, z);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(x);
benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
+ replace(c.begin(), c.end(), x, z);
+ benchmark::DoNotOptimize(c);
+ std::swap(x, z);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
index 3b139c54eeb12..1a51d3da4fc89 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -44,16 +44,15 @@ int main(int argc, char** argv) {
std::fill_n(std::back_inserter(c), size / 2, y);
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(z);
auto pred = [&x](auto& element) {
benchmark::DoNotOptimize(element);
return element == x;
};
replace_if(c.begin(), c.end(), pred, z);
- std::swap(x, z);
benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
+ std::swap(x, z);
}
})
->Arg(32)
@@ -85,16 +84,15 @@ int main(int argc, char** argv) {
}
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(z);
auto pred = [&x](auto& element) {
benchmark::DoNotOptimize(element);
return element == x;
};
replace_if(c.begin(), c.end(), pred, z);
- std::swap(x, z);
benchmark::DoNotOptimize(c);
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(z);
- benchmark::ClobberMemory();
+ std::swap(x, z);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
index 4ce2133c9a557..ded7d5018cdbe 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
@@ -32,9 +32,9 @@ int main(int argc, char** argv) {
std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
reverse(c.begin(), c.end());
benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})->Range(8, 1 << 15);
};
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
index c77cb9a560494..7e19eb71f059a 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
@@ -34,9 +34,10 @@ int main(int argc, char** argv) {
std::vector<ValueType> out(size);
for ([[maybe_unused]] auto _ : st) {
- reverse_copy(c.begin(), c.end(), out.begin());
benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
+ benchmark::DoNotOptimize(out);
+ auto result = reverse_copy(c.begin(), c.end(), out.begin());
+ benchmark::DoNotOptimize(result);
}
})->Range(8, 1 << 15);
};
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
index e32afbc87c9a0..8345f0941c62e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -35,10 +35,9 @@ int main(int argc, char** argv) {
auto middle = std::next(c.begin(), size / 2);
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
auto result = rotate(c.begin(), middle, c.end());
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
index 7972f1aba096e..4f685ba9a8c7e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
@@ -39,10 +39,10 @@ int main(int argc, char** argv) {
auto middle = std::next(c.begin(), size / 2);
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
index 87ab7517cb723..6cc789f460700 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
@@ -41,11 +41,10 @@ int main(int argc, char** argv) {
std::mt19937 rng;
for ([[maybe_unused]] auto _ : st) {
- auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
- benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c);
benchmark::DoNotOptimize(out);
- benchmark::ClobberMemory();
+ auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
+ benchmark::DoNotOptimize(result);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
index 24a3d34c65f09..906e825992b9d 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -36,10 +36,9 @@ int main(int argc, char** argv) {
auto const n = 9 * (size / 10); // shift all but 10% of the range
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
auto result = shift_left(c.begin(), c.end(), n);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
index 90fb507643149..ef55e55f3ca10 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -36,10 +36,9 @@ int main(int argc, char** argv) {
auto const n = 9 * (size / 10); // shift all but 10% of the range
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
auto result = shift_right(c.begin(), c.end(), n);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
index f50dff7635703..24f7fb6828977 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
@@ -35,9 +35,9 @@ int main(int argc, char** argv) {
std::mt19937 rng;
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
shuffle(c.begin(), c.end(), rng);
benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
index f7c2ff1252b09..541f4ae17cc7a 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
@@ -37,11 +37,12 @@ int main(int argc, char** argv) {
std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c1);
+ benchmark::DoNotOptimize(c2);
auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(c1);
benchmark::DoNotOptimize(c2);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
index b3e1195bcecb8..dd5e3783e6f13 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -45,12 +45,11 @@ int main(int argc, char** argv) {
};
for ([[maybe_unused]] auto _ : st) {
- auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
- benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(out);
benchmark::DoNotOptimize(c1);
benchmark::DoNotOptimize(c2);
- benchmark::ClobberMemory();
+ benchmark::DoNotOptimize(out);
+ auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
+ benchmark::DoNotOptimize(result);
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
index 837be87ada70b..e36a5f96c4e6f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -41,11 +41,10 @@ int main(int argc, char** argv) {
};
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
auto result = transform(c.begin(), c.end(), out.begin(), f);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(out);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index 8cc80982de70b..2a334447f953b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -46,10 +46,9 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
+ benchmark::DoNotOptimize(c[i]);
auto result = unique(c[i].begin(), c[i].end());
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
}
st.PauseTiming();
@@ -101,10 +100,9 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
+ benchmark::DoNotOptimize(c[i]);
auto result = unique(c[i].begin(), c[i].end());
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
}
st.PauseTiming();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index 3027953513958..a8bd2ed327c2b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -40,10 +40,10 @@ int main(int argc, char** argv) {
std::vector<ValueType> out(size);
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
auto result = unique_copy(c.begin(), c.end(), out.begin());
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
@@ -81,10 +81,10 @@ int main(int argc, char** argv) {
std::vector<ValueType> out(size);
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
auto result = unique_copy(c.begin(), c.end(), out.begin());
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
index 742feb873b25e..4d29e16ce9e1e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -48,10 +48,10 @@ int main(int argc, char** argv) {
};
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
@@ -95,10 +95,10 @@ int main(int argc, char** argv) {
};
for ([[maybe_unused]] auto _ : st) {
+ benchmark::DoNotOptimize(c);
+ benchmark::DoNotOptimize(out);
auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c);
- benchmark::ClobberMemory();
}
})
->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
index fb11f2e1adb9d..25f87e022023b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -52,10 +52,9 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
+ benchmark::DoNotOptimize(c[i]);
auto result = unique(c[i].begin(), c[i].end(), pred);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
}
st.PauseTiming();
@@ -113,10 +112,9 @@ int main(int argc, char** argv) {
while (st.KeepRunningBatch(BatchSize)) {
for (std::size_t i = 0; i != BatchSize; ++i) {
+ benchmark::DoNotOptimize(c[i]);
auto result = unique(c[i].begin(), c[i].end(), pred);
benchmark::DoNotOptimize(result);
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
}
st.PauseTiming();
More information about the libcxx-commits
mailing list