From 2bbe23fc7e7eb8ed6fe343d3a2d58c803a558433 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sat, 15 Feb 2025 21:36:38 +0100 Subject: [PATCH 01/15] [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 | 9 ++ .../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, 2155 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_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 b9964dac84acd..406b26f86a4c5 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -708,6 +708,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" @@ -732,7 +733,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 -#include -#include - -static void bm_fill_n_vector_bool(benchmark::State& state) { - std::vector 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 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 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 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" +#include "test_macros.h" + +template +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::random(); + ValueType y = Generate::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 +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 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::fill(vector)", std_fill); + bm>("std::fill(deque)", std_fill); + bm>("std::fill(list)", std_fill); + bm_vector_bool("std::fill(vector)", std_fill); + + // ranges::fill + bm>("ranges::fill(vector)", ranges_fill); + bm>("ranges::fill(deque)", ranges_fill); + bm>("ranges::fill(list)", ranges_fill); +#if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 + bm_vector_bool("ranges::fill(vector)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" +#include "test_macros.h" + +template +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::random(); + ValueType y = Generate::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 +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 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::fill_n(vector)", std_fill_n); + bm>("std::fill_n(deque)", std_fill_n); + bm>("std::fill_n(list)", std_fill_n); + bm_vector_bool("std::fill_n(vector)", std_fill_n); + + // ranges::fill_n + bm>("ranges::fill_n(vector)", ranges_fill_n); + bm>("ranges::fill_n(deque)", ranges_fill_n); + bm>("ranges::fill_n(list)", ranges_fill_n); +#if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 + bm_vector_bool("ranges::fill_n(vector)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::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::generate(vector)", std_generate); + bm>("std::generate(deque)", std_generate); + bm>("std::generate(list)", std_generate); + + // ranges::generate + bm>("ranges::generate(vector)", ranges_generate); + bm>("ranges::generate(deque)", ranges_generate); + bm>("ranges::generate(list)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::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::generate_n(vector)", std_generate_n); + bm>("std::generate_n(deque)", std_generate_n); + bm>("std::generate_n(list)", std_generate_n); + + // ranges::generate_n + bm>("ranges::generate_n(vector)", ranges_generate_n); + bm>("ranges::generate_n(deque)", ranges_generate_n); + bm>("ranges::generate_n(list)", 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 +#include +#include +#include +#include +#include +#include + +#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 +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::random(); + ValueType y = Generate::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 +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::random(); + ValueType y = Generate::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::remove(vector) (prefix)", std_remove); + bm_sprinkled>("std::remove(vector) (sprinkled)", std_remove); + + bm_prefix>("std::remove(deque) (prefix)", std_remove); + bm_sprinkled>("std::remove(deque) (sprinkled)", std_remove); + + bm_prefix>("std::remove(list) (prefix)", std_remove); + bm_sprinkled>("std::remove(list) (sprinkled)", std_remove); + + // ranges::remove + bm_prefix>("ranges::remove(vector) (prefix)", ranges_remove); + bm_sprinkled>("ranges::remove(vector) (sprinkled)", ranges_remove); + + bm_prefix>("ranges::remove(deque) (prefix)", ranges_remove); + bm_sprinkled>("ranges::remove(deque) (sprinkled)", ranges_remove); + + bm_prefix>("ranges::remove(list) (prefix)", ranges_remove); + bm_sprinkled>("ranges::remove(list) (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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove +// the prefix of x's from it. +template +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::random(); + ValueType y = Generate::random(); + std::fill_n(std::back_inserter(c), size / 2, x); + std::fill_n(std::back_inserter(c), size / 2, y); + + std::vector 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 +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::random(); + ValueType y = Generate::random(); + for (std::size_t i = 0; i != size; ++i) { + c.push_back(i % 2 == 0 ? x : y); + } + + std::vector 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::remove_copy(vector) (prefix)", std_remove_copy); + bm_sprinkled>("std::remove_copy(vector) (sprinkled)", std_remove_copy); + + bm_prefix>("std::remove_copy(deque) (prefix)", std_remove_copy); + bm_sprinkled>("std::remove_copy(deque) (sprinkled)", std_remove_copy); + + bm_prefix>("std::remove_copy(list) (prefix)", std_remove_copy); + bm_sprinkled>("std::remove_copy(list) (sprinkled)", std_remove_copy); + + // ranges::remove_copy + bm_prefix>("ranges::remove_copy(vector) (prefix)", ranges_remove_copy); + bm_sprinkled>("ranges::remove_copy(vector) (sprinkled)", ranges_remove_copy); + + bm_prefix>("ranges::remove_copy(deque) (prefix)", ranges_remove_copy); + bm_sprinkled>("ranges::remove_copy(deque) (sprinkled)", ranges_remove_copy); + + bm_prefix>("ranges::remove_copy(list) (prefix)", ranges_remove_copy); + bm_sprinkled>("ranges::remove_copy(list) (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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove +// the prefix of x's from it. +template +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::random(); + ValueType y = Generate::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 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 +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::random(); + ValueType y = Generate::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 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::remove_copy_if(vector) (prefix)", std_remove_copy_if); + bm_sprinkled>("std::remove_copy_if(vector) (sprinkled)", std_remove_copy_if); + + bm_prefix>("std::remove_copy_if(deque) (prefix)", std_remove_copy_if); + bm_sprinkled>("std::remove_copy_if(deque) (sprinkled)", std_remove_copy_if); + + bm_prefix>("std::remove_copy_if(list) (prefix)", std_remove_copy_if); + bm_sprinkled>("std::remove_copy_if(list) (sprinkled)", std_remove_copy_if); + + // ranges::remove_copy_if + bm_prefix>("ranges::remove_copy_if(vector) (prefix)", ranges_remove_copy_if); + bm_sprinkled>("ranges::remove_copy_if(vector) (sprinkled)", ranges_remove_copy_if); + + bm_prefix>("ranges::remove_copy_if(deque) (prefix)", ranges_remove_copy_if); + bm_sprinkled>("ranges::remove_copy_if(deque) (sprinkled)", ranges_remove_copy_if); + + bm_prefix>("ranges::remove_copy_if(list) (prefix)", ranges_remove_copy_if); + bm_sprinkled>("ranges::remove_copy_if(list) (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 +#include +#include +#include +#include +#include +#include + +#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 +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::random(); + ValueType y = Generate::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 +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::random(); + ValueType y = Generate::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::remove_if(vector) (prefix)", std_remove_if); + bm_sprinkled>("std::remove_if(vector) (sprinkled)", std_remove_if); + + bm_prefix>("std::remove_if(deque) (prefix)", std_remove_if); + bm_sprinkled>("std::remove_if(deque) (sprinkled)", std_remove_if); + + bm_prefix>("std::remove_if(list) (prefix)", std_remove_if); + bm_sprinkled>("std::remove_if(list) (sprinkled)", std_remove_if); + + // ranges::remove_if + bm_prefix>("ranges::remove_if(vector) (prefix)", ranges_remove_if); + bm_sprinkled>("ranges::remove_if(vector) (sprinkled)", ranges_remove_if); + + bm_prefix>("ranges::remove_if(deque) (prefix)", ranges_remove_if); + bm_sprinkled>("ranges::remove_if(deque) (sprinkled)", ranges_remove_if); + + bm_prefix>("ranges::remove_if(list) (prefix)", ranges_remove_if); + bm_sprinkled>("ranges::remove_if(list) (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 +#include +#include +#include +#include +#include +#include + +#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 +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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::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 +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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::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::replace(vector) (prefix)", std_replace); + bm_sprinkled>("std::replace(vector) (sprinkled)", std_replace); + + bm_prefix>("std::replace(deque) (prefix)", std_replace); + bm_sprinkled>("std::replace(deque) (sprinkled)", std_replace); + + bm_prefix>("std::replace(list) (prefix)", std_replace); + bm_sprinkled>("std::replace(list) (sprinkled)", std_replace); + + // ranges::replace + bm_prefix>("ranges::replace(vector) (prefix)", ranges_replace); + bm_sprinkled>("ranges::replace(vector) (sprinkled)", ranges_replace); + + bm_prefix>("ranges::replace(deque) (prefix)", ranges_replace); + bm_sprinkled>("ranges::replace(deque) (sprinkled)", ranges_replace); + + bm_prefix>("ranges::replace(list) (prefix)", ranges_replace); + bm_sprinkled>("ranges::replace(list) (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 +#include +#include +#include +#include +#include +#include + +#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 +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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::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 +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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::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::replace_if(vector) (prefix)", std_replace_if); + bm_sprinkled>("std::replace_if(vector) (sprinkled)", std_replace_if); + + bm_prefix>("std::replace_if(deque) (prefix)", std_replace_if); + bm_sprinkled>("std::replace_if(deque) (sprinkled)", std_replace_if); + + bm_prefix>("std::replace_if(list) (prefix)", std_replace_if); + bm_sprinkled>("std::replace_if(list) (sprinkled)", std_replace_if); + + // ranges::replace_if + bm_prefix>("ranges::replace_if(vector) (prefix)", ranges_replace_if); + bm_sprinkled>("ranges::replace_if(vector) (sprinkled)", ranges_replace_if); + + bm_prefix>("ranges::replace_if(deque) (prefix)", ranges_replace_if); + bm_sprinkled>("ranges::replace_if(deque) (sprinkled)", ranges_replace_if); + + bm_prefix>("ranges::replace_if(list) (prefix)", ranges_replace_if); + bm_sprinkled>("ranges::replace_if(list) (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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::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::reverse(vector)", std_reverse); + bm>("std::reverse(deque)", std_reverse); + bm>("std::reverse(list)", std_reverse); + + // ranges::reverse + bm>("ranges::reverse(vector)", ranges_reverse); + bm>("ranges::reverse(deque)", ranges_reverse); + bm>("ranges::reverse(list)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::random(); }); + + std::vector 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::reverse_copy(vector)", std_reverse_copy); + bm>("std::reverse_copy(deque)", std_reverse_copy); + bm>("std::reverse_copy(list)", std_reverse_copy); + + // ranges::reverse_copy + bm>("ranges::reverse_copy(vector)", ranges_reverse_copy); + bm>("ranges::reverse_copy(deque)", ranges_reverse_copy); + bm>("ranges::reverse_copy(list)", 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 index eb84eb5cdf25c..b6d7051b7ac9c 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp @@ -49,8 +49,17 @@ int main(int argc, char** argv) { ->Range(64, 1 << 20); }; + // std::rotate + bm.operator()>("std::rotate(vector)", std_rotate, 0.51); + bm.operator()>("std::rotate(deque)", std_rotate, 0.51); + bm.operator()>("std::rotate(list)", std_rotate, 0.51); bm.operator()>("std::rotate(vector) (by 1/4)", std_rotate, 0.25); bm.operator()>("std::rotate(vector) (by 51%)", std_rotate, 0.51); + + // ranges::rotate + bm.operator()>("rng::rotate(vector)", std::ranges::rotate, 0.51); + bm.operator()>("rng::rotate(deque)", std::ranges::rotate, 0.51); + bm.operator()>("rng::rotate(list)", std::ranges::rotate, 0.51); #if TEST_STD_VER >= 23 // vector::iterator is not std::permutable before C++23 bm.operator()>("rng::rotate(vector) (by 1/4)", std::ranges::rotate, 0.25); bm.operator()>("rng::rotate(vector) (by 51%)", std::ranges::rotate, 0.51); 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::random(); }); + + std::vector 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::rotate_copy(vector)", std_rotate_copy); + bm>("std::rotate_copy(deque)", std_rotate_copy); + bm>("std::rotate_copy(list)", std_rotate_copy); + + // ranges::rotate_copy + bm>("ranges::rotate_copy(vector)", ranges_rotate_copy); + bm>("ranges::rotate_copy(deque)", ranges_rotate_copy); + bm>("ranges::rotate_copy(list)", 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 +#include +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::random(); }); + + std::vector 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::sample(vector)", std_sample); + bm>("std::sample(deque)", std_sample); + bm>("std::sample(list)", std_sample); + + // ranges::sample + bm>("ranges::sample(vector)", ranges_sample); + bm>("ranges::sample(deque)", ranges_sample); + bm>("ranges::sample(list)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::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::shift_left(vector)", std_shift_left); + bm>("std::shift_left(deque)", std_shift_left); + bm>("std::shift_left(list)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::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::shift_right(vector)", std_shift_right); + bm>("std::shift_right(deque)", std_shift_right); + bm>("std::shift_right(list)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::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::shuffle(vector)", std_shuffle); + bm>("std::shuffle(deque)", std_shuffle); + + // ranges::shuffle + bm>("ranges::shuffle(vector)", ranges_shuffle); + bm>("ranges::shuffle(deque)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::random(); }); + std::generate_n(std::back_inserter(c2), size, [] { return Generate::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::swap_ranges(vector)", std_swap_ranges); + bm>("std::swap_ranges(deque)", std_swap_ranges); + bm>("std::swap_ranges(list)", std_swap_ranges); + + // ranges::swap_ranges + bm>("ranges::swap_ranges(vector)", ranges_swap_ranges); + bm>("ranges::swap_ranges(deque)", ranges_swap_ranges); + bm>("ranges::swap_ranges(list)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::random(); }); + std::generate_n(std::back_inserter(c2), size, [] { return Generate::random(); }); + + std::vector 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::transform(vector, vector)", std_transform); + bm>("std::transform(deque, deque)", std_transform); + bm>("std::transform(list, list)", std_transform); + + // ranges::transform + bm>("ranges::transform(vector, vector)", ranges_transform); + bm>("ranges::transform(deque, deque)", ranges_transform); + bm>("ranges::transform(list, list)", 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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +template +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::random(); }); + + std::vector 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::transform(vector) (identity transform)", std_transform); + bm>("std::transform(deque) (identity transform)", std_transform); + bm>("std::transform(list) (identity transform)", std_transform); + + // ranges::transform + bm>("ranges::transform(vector) (identity transform)", ranges_transform); + bm>("ranges::transform(deque) (identity transform)", ranges_transform); + bm>("ranges::transform(list) (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 +#include +#include +#include +#include +#include +#include + +#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 +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::random(); + ValueType y = Generate::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 +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::random(); + ValueType y = Generate::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::unique(vector) (contiguous)", std_unique); + bm_sprinkled>("std::unique(vector) (sprinkled)", std_unique); + + bm_contiguous>("std::unique(deque) (contiguous)", std_unique); + bm_sprinkled>("std::unique(deque) (sprinkled)", std_unique); + + bm_contiguous>("std::unique(list) (contiguous)", std_unique); + bm_sprinkled>("std::unique(list) (sprinkled)", std_unique); + + // ranges::unique + bm_contiguous>("ranges::unique(vector) (contiguous)", ranges_unique); + bm_sprinkled>("ranges::unique(vector) (sprinkled)", ranges_unique); + + bm_contiguous>("ranges::unique(deque) (contiguous)", ranges_unique); + bm_sprinkled>("ranges::unique(deque) (sprinkled)", ranges_unique); + + bm_contiguous>("ranges::unique(list) (contiguous)", ranges_unique); + bm_sprinkled>("ranges::unique(list) (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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the +// adjacent equal elements. +template +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::random(); + ValueType y = Generate::random(); + auto half = size / 2; + std::fill_n(std::fill_n(c.begin(), half, x), half, y); + + std::vector 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 +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::random(); + ValueType y = Generate::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 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::unique_copy(vector) (contiguous)", std_unique_copy); + bm_sprinkled>("std::unique_copy(vector) (sprinkled)", std_unique_copy); + + bm_contiguous>("std::unique_copy(deque) (contiguous)", std_unique_copy); + bm_sprinkled>("std::unique_copy(deque) (sprinkled)", std_unique_copy); + + bm_contiguous>("std::unique_copy(list) (contiguous)", std_unique_copy); + bm_sprinkled>("std::unique_copy(list) (sprinkled)", std_unique_copy); + + // ranges::unique_copy + bm_contiguous>("ranges::unique_copy(vector) (contiguous)", ranges_unique_copy); + bm_sprinkled>("ranges::unique_copy(vector) (sprinkled)", ranges_unique_copy); + + bm_contiguous>("ranges::unique_copy(deque) (contiguous)", ranges_unique_copy); + bm_sprinkled>("ranges::unique_copy(deque) (sprinkled)", ranges_unique_copy); + + bm_contiguous>("ranges::unique_copy(list) (contiguous)", ranges_unique_copy); + bm_sprinkled>("ranges::unique_copy(list) (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 +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the +// adjacent equal elements. +template +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::random(); + ValueType y = Generate::random(); + auto half = size / 2; + std::fill_n(std::fill_n(c.begin(), half, x), half, y); + + std::vector 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 +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::random(); + ValueType y = Generate::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 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::unique_copy(vector, pred) (contiguous)", std_unique_copy); + bm_sprinkled>("std::unique_copy(vector, pred) (sprinkled)", std_unique_copy); + + bm_contiguous>("std::unique_copy(deque, pred) (contiguous)", std_unique_copy); + bm_sprinkled>("std::unique_copy(deque, pred) (sprinkled)", std_unique_copy); + + bm_contiguous>("std::unique_copy(list, pred) (contiguous)", std_unique_copy); + bm_sprinkled>("std::unique_copy(list, pred) (sprinkled)", std_unique_copy); + + // ranges::unique_copy + bm_contiguous>("ranges::unique_copy(vector, pred) (contiguous)", ranges_unique_copy); + bm_sprinkled>("ranges::unique_copy(vector, pred) (sprinkled)", ranges_unique_copy); + + bm_contiguous>("ranges::unique_copy(deque, pred) (contiguous)", ranges_unique_copy); + bm_sprinkled>("ranges::unique_copy(deque, pred) (sprinkled)", ranges_unique_copy); + + bm_contiguous>("ranges::unique_copy(list, pred) (contiguous)", ranges_unique_copy); + bm_sprinkled>("ranges::unique_copy(list, 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 +#include +#include +#include +#include +#include +#include + +#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 +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::random(); + ValueType y = Generate::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 +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::random(); + ValueType y = Generate::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::unique(vector, pred) (contiguous)", std_unique); + bm_sprinkled>("std::unique(vector, pred) (sprinkled)", std_unique); + + bm_contiguous>("std::unique(deque, pred) (contiguous)", std_unique); + bm_sprinkled>("std::unique(deque, pred) (sprinkled)", std_unique); + + bm_contiguous>("std::unique(list, pred) (contiguous)", std_unique); + bm_sprinkled>("std::unique(list, pred) (sprinkled)", std_unique); + + // ranges::unique + bm_contiguous>("ranges::unique(vector, pred) (contiguous)", ranges_unique); + bm_sprinkled>("ranges::unique(vector, pred) (sprinkled)", ranges_unique); + + bm_contiguous>("ranges::unique(deque, pred) (contiguous)", ranges_unique); + bm_sprinkled>("ranges::unique(deque, pred) (sprinkled)", ranges_unique); + + bm_contiguous>("ranges::unique(list, pred) (contiguous)", ranges_unique); + bm_sprinkled>("ranges::unique(list, 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 -#include -#include -#include - -#include -#include "../GenerateInput.h" - -template -static void bm_reverse(benchmark::State& state) { - std::size_t const n = state.range(); - std::vector vec; - std::generate_n(std::back_inserter(vec), n, [] { return Generate::cheap(); }); - for (auto _ : state) { - std::reverse(vec.begin(), vec.end()); - benchmark::DoNotOptimize(vec); - } -} -BENCHMARK(bm_reverse)->Name("std::reverse(vector)")->DenseRange(1, 8)->Range(16, 1 << 20); -BENCHMARK(bm_reverse)->Name("std::reverse(vector)")->DenseRange(1, 8)->Range(16, 1 << 20); - -template -static void bm_ranges_reverse(benchmark::State& state) { - std::size_t const n = state.range(); - std::vector vec; - std::generate_n(std::back_inserter(vec), n, [] { return Generate::cheap(); }); - for (auto _ : state) { - std::ranges::reverse(vec.begin(), vec.end()); - benchmark::DoNotOptimize(vec); - } -} -BENCHMARK(bm_ranges_reverse)->Name("ranges::reverse(vector)")->DenseRange(1, 8)->Range(16, 1 << 20); -BENCHMARK(bm_ranges_reverse) - ->Name("ranges::reverse(vector)") - ->DenseRange(1, 8) - ->Range(16, 1 << 20); - -BENCHMARK_MAIN(); From db70c84830989e78a5415387c49fda729770bee0 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 19 Feb 2025 15:10:48 -0500 Subject: [PATCH 02/15] 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 +#include +#include +#include +#include +#include +#include + +#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 = [](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::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::move(vector)", std_move); + bm.operator()>("std::move(deque)", std_move); + bm.operator()>("std::move(list)", std_move); + bm.operator()>("rng::move(vector)", std::ranges::move); + bm.operator()>("rng::move(deque)", std::ranges::move); + bm.operator()>("rng::move(list)", std::ranges::move); + } + + // {std,ranges}::move(vector) + { + auto bm = [](std::string name, auto move) { + benchmark::RegisterBenchmark(name, [move](auto& st) { + std::size_t const n = st.range(0); + std::vector c1(n, true); + std::vector c2(n, false); + + std::vector* in = &c1; + std::vector* 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()("std::move(vector) (aligned)", std_move); + bm.operator()("std::move(vector) (unaligned)", std_move); +#if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 + bm.operator()("rng::move(vector) (aligned)", std::ranges::move); + bm.operator()("rng::move(vector) (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 +#include +#include +#include +#include +#include +#include + +#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 = [](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::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::move_backward(vector)", std_move_backward); + bm.operator()>("std::move_backward(deque)", std_move_backward); + bm.operator()>("std::move_backward(list)", std_move_backward); + bm.operator()>("rng::move_backward(vector)", std::ranges::move_backward); + bm.operator()>("rng::move_backward(deque)", std::ranges::move_backward); + bm.operator()>("rng::move_backward(list)", std::ranges::move_backward); + } + + // {std,ranges}::move_backward(vector) + { + auto bm = [](std::string name, auto move_backward) { + benchmark::RegisterBenchmark(name, [move_backward](auto& st) { + std::size_t const n = st.range(0); + std::vector c1(n, true); + std::vector c2(n, false); + + std::vector* in = &c1; + std::vector* 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()("std::move_backward(vector) (aligned)", std_move_backward); + bm.operator()("std::move_backward(vector) (unaligned)", std_move_backward); +#if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 + bm.operator()("rng::move_backward(vector) (aligned)", std::ranges::move_backward); + bm.operator()("rng::move_backward(vector) (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 -#include -#include -#include - -template -void bm_ranges_move_vb(benchmark::State& state) { - auto n = state.range(); - std::vector v1(n, true); - std::vector v2(n, false); - benchmark::DoNotOptimize(v1); - benchmark::DoNotOptimize(v2); - std::vector* in = &v1; - std::vector* 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 -void bm_move_vb(benchmark::State& state) { - auto n = state.range(); - std::vector v1(n, true); - std::vector v2(n, false); - benchmark::DoNotOptimize(v1); - benchmark::DoNotOptimize(v2); - std::vector* in = &v1; - std::vector* 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) - ->Name("bm_ranges_move_vb_aligned") - ->Range(8, 1 << 16) - ->DenseRange(102400, 204800, 4096); -BENCHMARK(bm_ranges_move_vb)->Name("bm_ranges_move_vb_unaligned")->Range(8, 1 << 20); - -BENCHMARK(bm_move_vb)->Name("bm_move_vb_aligned")->Range(8, 1 << 20); -BENCHMARK(bm_move_vb)->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 -#include -#include -#include - -template -void bm_ranges_move_backward_vb(benchmark::State& state) { - auto n = state.range(); - std::vector v1(n, true); - std::vector v2(n, false); - benchmark::DoNotOptimize(v1); - benchmark::DoNotOptimize(v2); - std::vector* in = &v1; - std::vector* 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 -void bm_move_backward_vb(benchmark::State& state) { - auto n = state.range(); - std::vector v1(n, true); - std::vector v2(n, false); - benchmark::DoNotOptimize(v1); - benchmark::DoNotOptimize(v2); - std::vector* in = &v1; - std::vector* 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) - ->Name("bm_ranges_move_backward_vb_aligned") - ->Range(8, 1 << 16) - ->DenseRange(102400, 204800, 4096); -BENCHMARK(bm_ranges_move_backward_vb)->Name("bm_ranges_move_backward_vb_unaligned")->Range(8, 1 << 20); - -BENCHMARK(bm_move_backward_vb)->Name("bm_move_backward_vb_aligned")->Range(8, 1 << 20); -BENCHMARK(bm_move_backward_vb)->Name("bm_move_backward_vb_unaligned")->Range(8, 1 << 20); - -BENCHMARK_MAIN(); From 3144f08d30238c2a1187499efbc60c8c08c96159 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 19 Feb 2025 16:12:19 -0500 Subject: [PATCH 03/15] 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 | 109 +++++++-- .../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, 1500 insertions(+), 1423 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 -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::random(); - ValueType y = Generate::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 -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 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 = [](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::random(); + ValueType y = Generate::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::fill(vector)", std_fill); + bm.operator()>("std::fill(deque)", std_fill); + bm.operator()>("std::fill(list)", std_fill); + bm.operator()>("rng::fill(vector)", std::ranges::fill); + bm.operator()>("rng::fill(deque)", std::ranges::fill); + bm.operator()>("rng::fill(list)", std::ranges::fill); + } - // std::fill - bm>("std::fill(vector)", std_fill); - bm>("std::fill(deque)", std_fill); - bm>("std::fill(list)", std_fill); - bm_vector_bool("std::fill(vector)", std_fill); + // {std,ranges}::fill(vector) + { + 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 c(size, y); - // ranges::fill - bm>("ranges::fill(vector)", ranges_fill); - bm>("ranges::fill(deque)", ranges_fill); - bm>("ranges::fill(list)", 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)", std_fill); #if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 - bm_vector_bool("ranges::fill(vector)", ranges_fill); + bm("rng::fill(vector)", 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 -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::random(); - ValueType y = Generate::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 -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 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 = [](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::random(); + ValueType y = Generate::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::fill_n(vector)", std_fill_n); + bm.operator()>("std::fill_n(deque)", std_fill_n); + bm.operator()>("std::fill_n(list)", std_fill_n); + bm.operator()>("rng::fill_n(vector)", std::ranges::fill_n); + bm.operator()>("rng::fill_n(deque)", std::ranges::fill_n); + bm.operator()>("rng::fill_n(list)", std::ranges::fill_n); + } - // std::fill_n - bm>("std::fill_n(vector)", std_fill_n); - bm>("std::fill_n(deque)", std_fill_n); - bm>("std::fill_n(list)", std_fill_n); - bm_vector_bool("std::fill_n(vector)", std_fill_n); + // {std,ranges}::fill_n(vector) + { + 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 c(size, y); - // ranges::fill_n - bm>("ranges::fill_n(vector)", ranges_fill_n); - bm>("ranges::fill_n(deque)", ranges_fill_n); - bm>("ranges::fill_n(list)", 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)", std_fill_n); #if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 - bm_vector_bool("ranges::fill_n(vector)", ranges_fill_n); + bm("rng::fill_n(vector)", 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 -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::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::generate(vector)", std_generate); - bm>("std::generate(deque)", std_generate); - bm>("std::generate(list)", std_generate); - - // ranges::generate - bm>("ranges::generate(vector)", ranges_generate); - bm>("ranges::generate(deque)", ranges_generate); - bm>("ranges::generate(list)", ranges_generate); + auto std_generate = [](auto first, auto last, auto f) { return std::generate(first, last, f); }; + + // {std,ranges}::generate + { + auto bm = [](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::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::generate(vector)", std_generate); + bm.operator()>("std::generate(deque)", std_generate); + bm.operator()>("std::generate(list)", std_generate); + bm.operator()>("rng::generate(vector)", std::ranges::generate); + bm.operator()>("rng::generate(deque)", std::ranges::generate); + bm.operator()>("rng::generate(list)", 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 -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::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::generate_n(vector)", std_generate_n); - bm>("std::generate_n(deque)", std_generate_n); - bm>("std::generate_n(list)", std_generate_n); - - // ranges::generate_n - bm>("ranges::generate_n(vector)", ranges_generate_n); - bm>("ranges::generate_n(deque)", ranges_generate_n); - bm>("ranges::generate_n(list)", 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 = [](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::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::generate_n(vector)", std_generate_n); + bm.operator()>("std::generate_n(deque)", std_generate_n); + bm.operator()>("std::generate_n(list)", std_generate_n); + bm.operator()>("rng::generate_n(vector)", std::ranges::generate_n); + bm.operator()>("rng::generate_n(deque)", std::ranges::generate_n); + bm.operator()>("rng::generate_n(list)", 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 -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::random(); - ValueType y = Generate::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 -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::random(); - ValueType y = Generate::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::remove(vector) (prefix)", std_remove); - bm_sprinkled>("std::remove(vector) (sprinkled)", std_remove); - - bm_prefix>("std::remove(deque) (prefix)", std_remove); - bm_sprinkled>("std::remove(deque) (sprinkled)", std_remove); - - bm_prefix>("std::remove(list) (prefix)", std_remove); - bm_sprinkled>("std::remove(list) (sprinkled)", std_remove); - - // ranges::remove - bm_prefix>("ranges::remove(vector) (prefix)", ranges_remove); - bm_sprinkled>("ranges::remove(vector) (sprinkled)", ranges_remove); - - bm_prefix>("ranges::remove(deque) (prefix)", ranges_remove); - bm_sprinkled>("ranges::remove(deque) (sprinkled)", ranges_remove); - - bm_prefix>("ranges::remove(list) (prefix)", ranges_remove); - bm_sprinkled>("ranges::remove(list) (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 = [](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::random(); + ValueType y = Generate::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::remove(vector) (prefix)", std_remove); + bm.operator()>("std::remove(deque) (prefix)", std_remove); + bm.operator()>("std::remove(list) (prefix)", std_remove); + bm.operator()>("rng::remove(vector) (prefix)", std::ranges::remove); + bm.operator()>("rng::remove(deque) (prefix)", std::ranges::remove); + bm.operator()>("rng::remove(list) (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 = [](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::random(); + ValueType y = Generate::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::remove(vector) (sprinkled)", std_remove); + bm.operator()>("std::remove(deque) (sprinkled)", std_remove); + bm.operator()>("std::remove(list) (sprinkled)", std_remove); + bm.operator()>("rng::remove(vector) (sprinkled)", std::ranges::remove); + bm.operator()>("rng::remove(deque) (sprinkled)", std::ranges::remove); + bm.operator()>("rng::remove(list) (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 -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::random(); - ValueType y = Generate::random(); - std::fill_n(std::back_inserter(c), size / 2, x); - std::fill_n(std::back_inserter(c), size / 2, y); - - std::vector 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 -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::random(); - ValueType y = Generate::random(); - for (std::size_t i = 0; i != size; ++i) { - c.push_back(i % 2 == 0 ? x : y); - } - - std::vector 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::remove_copy(vector) (prefix)", std_remove_copy); - bm_sprinkled>("std::remove_copy(vector) (sprinkled)", std_remove_copy); - - bm_prefix>("std::remove_copy(deque) (prefix)", std_remove_copy); - bm_sprinkled>("std::remove_copy(deque) (sprinkled)", std_remove_copy); - - bm_prefix>("std::remove_copy(list) (prefix)", std_remove_copy); - bm_sprinkled>("std::remove_copy(list) (sprinkled)", std_remove_copy); - - // ranges::remove_copy - bm_prefix>("ranges::remove_copy(vector) (prefix)", ranges_remove_copy); - bm_sprinkled>("ranges::remove_copy(vector) (sprinkled)", ranges_remove_copy); - - bm_prefix>("ranges::remove_copy(deque) (prefix)", ranges_remove_copy); - bm_sprinkled>("ranges::remove_copy(deque) (sprinkled)", ranges_remove_copy); - bm_prefix>("ranges::remove_copy(list) (prefix)", ranges_remove_copy); - bm_sprinkled>("ranges::remove_copy(list) (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 = [](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::random(); + ValueType y = Generate::random(); + std::fill_n(std::back_inserter(c), size / 2, x); + std::fill_n(std::back_inserter(c), size / 2, y); + + std::vector 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::remove_copy(vector) (prefix)", std_remove_copy); + bm.operator()>("std::remove_copy(deque) (prefix)", std_remove_copy); + bm.operator()>("std::remove_copy(list) (prefix)", std_remove_copy); + bm.operator()>("rng::remove_copy(vector) (prefix)", std::ranges::remove_copy); + bm.operator()>("rng::remove_copy(deque) (prefix)", std::ranges::remove_copy); + bm.operator()>("rng::remove_copy(list) (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 = [](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::random(); + ValueType y = Generate::random(); + for (std::size_t i = 0; i != size; ++i) { + c.push_back(i % 2 == 0 ? x : y); + } + + std::vector 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::remove_copy(vector) (sprinkled)", std_remove_copy); + bm.operator()>("std::remove_copy(deque) (sprinkled)", std_remove_copy); + bm.operator()>("std::remove_copy(list) (sprinkled)", std_remove_copy); + bm.operator()>("rng::remove_copy(vector) (sprinkled)", std::ranges::remove_copy); + bm.operator()>("rng::remove_copy(deque) (sprinkled)", std::ranges::remove_copy); + bm.operator()>("rng::remove_copy(list) (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 -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::random(); - ValueType y = Generate::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 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 -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::random(); - ValueType y = Generate::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 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::remove_copy_if(vector) (prefix)", std_remove_copy_if); - bm_sprinkled>("std::remove_copy_if(vector) (sprinkled)", std_remove_copy_if); - - bm_prefix>("std::remove_copy_if(deque) (prefix)", std_remove_copy_if); - bm_sprinkled>("std::remove_copy_if(deque) (sprinkled)", std_remove_copy_if); - bm_prefix>("std::remove_copy_if(list) (prefix)", std_remove_copy_if); - bm_sprinkled>("std::remove_copy_if(list) (sprinkled)", std_remove_copy_if); - - // ranges::remove_copy_if - bm_prefix>("ranges::remove_copy_if(vector) (prefix)", ranges_remove_copy_if); - bm_sprinkled>("ranges::remove_copy_if(vector) (sprinkled)", ranges_remove_copy_if); - - bm_prefix>("ranges::remove_copy_if(deque) (prefix)", ranges_remove_copy_if); - bm_sprinkled>("ranges::remove_copy_if(deque) (sprinkled)", ranges_remove_copy_if); - - bm_prefix>("ranges::remove_copy_if(list) (prefix)", ranges_remove_copy_if); - bm_sprinkled>("ranges::remove_copy_if(list) (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 = [](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::random(); + ValueType y = Generate::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 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::remove_copy_if(vector) (prefix)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(deque) (prefix)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(list) (prefix)", std_remove_copy_if); + bm.operator()>("rng::remove_copy_if(vector) (prefix)", std::ranges::remove_copy_if); + bm.operator()>("rng::remove_copy_if(deque) (prefix)", std::ranges::remove_copy_if); + bm.operator()>("rng::remove_copy_if(list) (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 = [](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::random(); + ValueType y = Generate::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 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::remove_copy_if(vector) (sprinkled)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(deque) (sprinkled)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(list) (sprinkled)", std_remove_copy_if); + bm.operator()>("rng::remove_copy_if(vector) (sprinkled)", std::ranges::remove_copy_if); + bm.operator()>("rng::remove_copy_if(deque) (sprinkled)", std::ranges::remove_copy_if); + bm.operator()>("rng::remove_copy_if(list) (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 -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::random(); - ValueType y = Generate::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 -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::random(); - ValueType y = Generate::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 = [](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::random(); + ValueType y = Generate::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::remove_if(vector) (prefix)", std_remove_if); + bm.operator()>("std::remove_if(deque) (prefix)", std_remove_if); + bm.operator()>("std::remove_if(list) (prefix)", std_remove_if); + bm.operator()>("rng::remove_if(vector) (prefix)", std::ranges::remove_if); + bm.operator()>("rng::remove_if(deque) (prefix)", std::ranges::remove_if); + bm.operator()>("rng::remove_if(list) (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 = [](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::random(); + ValueType y = Generate::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::remove_if(vector) (prefix)", std_remove_if); - bm_sprinkled>("std::remove_if(vector) (sprinkled)", std_remove_if); - - bm_prefix>("std::remove_if(deque) (prefix)", std_remove_if); - bm_sprinkled>("std::remove_if(deque) (sprinkled)", std_remove_if); - - bm_prefix>("std::remove_if(list) (prefix)", std_remove_if); - bm_sprinkled>("std::remove_if(list) (sprinkled)", std_remove_if); - - // ranges::remove_if - bm_prefix>("ranges::remove_if(vector) (prefix)", ranges_remove_if); - bm_sprinkled>("ranges::remove_if(vector) (sprinkled)", ranges_remove_if); - - bm_prefix>("ranges::remove_if(deque) (prefix)", ranges_remove_if); - bm_sprinkled>("ranges::remove_if(deque) (sprinkled)", ranges_remove_if); - - bm_prefix>("ranges::remove_if(list) (prefix)", ranges_remove_if); - bm_sprinkled>("ranges::remove_if(list) (sprinkled)", ranges_remove_if); + bm.operator()>("std::remove_if(vector) (sprinkled)", std_remove_if); + bm.operator()>("std::remove_if(deque) (sprinkled)", std_remove_if); + bm.operator()>("std::remove_if(list) (sprinkled)", std_remove_if); + bm.operator()>("rng::remove_if(vector) (sprinkled)", std::ranges::remove_if); + bm.operator()>("rng::remove_if(deque) (sprinkled)", std::ranges::remove_if); + bm.operator()>("rng::remove_if(list) (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 -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::random(); - ValueType y = Generate::random(); - ValueType z = Generate::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 -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::random(); - ValueType y = Generate::random(); - ValueType z = Generate::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::replace(vector) (prefix)", std_replace); - bm_sprinkled>("std::replace(vector) (sprinkled)", std_replace); - - bm_prefix>("std::replace(deque) (prefix)", std_replace); - bm_sprinkled>("std::replace(deque) (sprinkled)", std_replace); + auto std_replace = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); }; - bm_prefix>("std::replace(list) (prefix)", std_replace); - bm_sprinkled>("std::replace(list) (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 = [](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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::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>("ranges::replace(vector) (prefix)", ranges_replace); - bm_sprinkled>("ranges::replace(vector) (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::replace(vector) (prefix)", std_replace); + bm.operator()>("std::replace(deque) (prefix)", std_replace); + bm.operator()>("std::replace(list) (prefix)", std_replace); + bm.operator()>("rng::replace(vector) (prefix)", std::ranges::replace); + bm.operator()>("rng::replace(deque) (prefix)", std::ranges::replace); + bm.operator()>("rng::replace(list) (prefix)", std::ranges::replace); + } - bm_prefix>("ranges::replace(deque) (prefix)", ranges_replace); - bm_sprinkled>("ranges::replace(deque) (sprinkled)", ranges_replace); + // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy. + { + auto bm = [](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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::random(); + for (std::size_t i = 0; i != size; ++i) { + c.push_back(i % 2 == 0 ? x : y); + } - bm_prefix>("ranges::replace(list) (prefix)", ranges_replace); - bm_sprinkled>("ranges::replace(list) (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::replace(vector) (sprinkled)", std_replace); + bm.operator()>("std::replace(deque) (sprinkled)", std_replace); + bm.operator()>("std::replace(list) (sprinkled)", std_replace); + bm.operator()>("rng::replace(vector) (sprinkled)", std::ranges::replace); + bm.operator()>("rng::replace(deque) (sprinkled)", std::ranges::replace); + bm.operator()>("rng::replace(list) (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 -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::random(); - ValueType y = Generate::random(); - ValueType z = Generate::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 -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::random(); - ValueType y = Generate::random(); - ValueType z = Generate::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::replace_if(vector) (prefix)", std_replace_if); - bm_sprinkled>("std::replace_if(vector) (sprinkled)", std_replace_if); - - bm_prefix>("std::replace_if(deque) (prefix)", std_replace_if); - bm_sprinkled>("std::replace_if(deque) (sprinkled)", std_replace_if); - bm_prefix>("std::replace_if(list) (prefix)", std_replace_if); - bm_sprinkled>("std::replace_if(list) (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 = [](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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::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>("ranges::replace_if(vector) (prefix)", ranges_replace_if); - bm_sprinkled>("ranges::replace_if(vector) (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::replace_if(vector) (prefix)", std_replace_if); + bm.operator()>("std::replace_if(deque) (prefix)", std_replace_if); + bm.operator()>("std::replace_if(list) (prefix)", std_replace_if); + bm.operator()>("rng::replace_if(vector) (prefix)", std::ranges::replace_if); + bm.operator()>("rng::replace_if(deque) (prefix)", std::ranges::replace_if); + bm.operator()>("rng::replace_if(list) (prefix)", std::ranges::replace_if); + } - bm_prefix>("ranges::replace_if(deque) (prefix)", ranges_replace_if); - bm_sprinkled>("ranges::replace_if(deque) (sprinkled)", ranges_replace_if); + // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy. + { + auto bm = [](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::random(); + ValueType y = Generate::random(); + ValueType z = Generate::random(); + for (std::size_t i = 0; i != size; ++i) { + c.push_back(i % 2 == 0 ? x : y); + } - bm_prefix>("ranges::replace_if(list) (prefix)", ranges_replace_if); - bm_sprinkled>("ranges::replace_if(list) (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::replace_if(vector) (sprinkled)", std_replace_if); + bm.operator()>("std::replace_if(deque) (sprinkled)", std_replace_if); + bm.operator()>("std::replace_if(list) (sprinkled)", std_replace_if); + bm.operator()>("rng::replace_if(vector) (sprinkled)", std::ranges::replace_if); + bm.operator()>("rng::replace_if(deque) (sprinkled)", std::ranges::replace_if); + bm.operator()>("rng::replace_if(list) (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 -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::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::reverse(vector)", std_reverse); - bm>("std::reverse(deque)", std_reverse); - bm>("std::reverse(list)", std_reverse); - - // ranges::reverse - bm>("ranges::reverse(vector)", ranges_reverse); - bm>("ranges::reverse(deque)", ranges_reverse); - bm>("ranges::reverse(list)", ranges_reverse); + auto std_reverse = [](auto first, auto last) { return std::reverse(first, last); }; + + // {std,ranges}::reverse(normal container) + { + auto bm = [](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::random(); }); + + for ([[maybe_unused]] auto _ : st) { + reverse(c.begin(), c.end()); + benchmark::DoNotOptimize(c); + benchmark::ClobberMemory(); + } + })->Range(8, 1 << 15); + }; + bm.operator()>("std::reverse(vector)", std_reverse); + bm.operator()>("std::reverse(deque)", std_reverse); + bm.operator()>("std::reverse(list)", std_reverse); + bm.operator()>("rng::reverse(vector)", std::ranges::reverse); + bm.operator()>("rng::reverse(deque)", std::ranges::reverse); + bm.operator()>("rng::reverse(list)", 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 -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::random(); }); - - std::vector 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::reverse_copy(vector)", std_reverse_copy); - bm>("std::reverse_copy(deque)", std_reverse_copy); - bm>("std::reverse_copy(list)", std_reverse_copy); - - // ranges::reverse_copy - bm>("ranges::reverse_copy(vector)", ranges_reverse_copy); - bm>("ranges::reverse_copy(deque)", ranges_reverse_copy); - bm>("ranges::reverse_copy(list)", 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 = [](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::random(); }); + + std::vector 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::reverse_copy(vector)", std_reverse_copy); + bm.operator()>("std::reverse_copy(deque)", std_reverse_copy); + bm.operator()>("std::reverse_copy(list)", std_reverse_copy); + bm.operator()>("rng::reverse_copy(vector)", std::ranges::reverse_copy); + bm.operator()>("rng::reverse_copy(deque)", std::ranges::reverse_copy); + bm.operator()>("rng::reverse_copy(list)", 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 b6d7051b7ac9c..2aa0d6b696e59 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -45,25 +44,105 @@ int main(int argc, char** argv) { }) ->Arg(32) ->Arg(50) // non power-of-two - ->RangeMultiplier(2) - ->Range(64, 1 << 20); + ->Arg(1024) + ->Arg(8192); }; + bm.operator()>("std::rotate(vector) (by 1/4)", std_rotate, 0.25); + bm.operator()>("std::rotate(deque) (by 1/4)", std_rotate, 0.25); + bm.operator()>("std::rotate(list) (by 1/4)", std_rotate, 0.25); + bm.operator()>("rng::rotate(vector) (by 1/4)", std::ranges::rotate, 0.25); + bm.operator()>("rng::rotate(deque) (by 1/4)", std::ranges::rotate, 0.25); + bm.operator()>("rng::rotate(list) (by 1/4)", std::ranges::rotate, 0.25); + + bm.operator()>("std::rotate(vector) (by 1/3)", std_rotate, 0.33); + bm.operator()>("std::rotate(deque) (by 1/3)", std_rotate, 0.33); + bm.operator()>("std::rotate(list) (by 1/3)", std_rotate, 0.33); + bm.operator()>("rng::rotate(vector) (by 1/3)", std::ranges::rotate, 0.33); + bm.operator()>("rng::rotate(deque) (by 1/3)", std::ranges::rotate, 0.33); + bm.operator()>("rng::rotate(list) (by 1/3)", std::ranges::rotate, 0.33); + + bm.operator()>("std::rotate(vector) (by 1/2)", std_rotate, 0.50); + bm.operator()>("std::rotate(deque) (by 1/2)", std_rotate, 0.50); + bm.operator()>("std::rotate(list) (by 1/2)", std_rotate, 0.50); + bm.operator()>("rng::rotate(vector) (by 1/2)", std::ranges::rotate, 0.50); + bm.operator()>("rng::rotate(deque) (by 1/2)", std::ranges::rotate, 0.50); + bm.operator()>("rng::rotate(list) (by 1/2)", std::ranges::rotate, 0.50); - // std::rotate - bm.operator()>("std::rotate(vector)", std_rotate, 0.51); - bm.operator()>("std::rotate(deque)", std_rotate, 0.51); - bm.operator()>("std::rotate(list)", std_rotate, 0.51); bm.operator()>("std::rotate(vector) (by 1/4)", std_rotate, 0.25); - bm.operator()>("std::rotate(vector) (by 51%)", std_rotate, 0.51); + bm.operator()>("std::rotate(vector) (by 1/3)", std_rotate, 0.33); + bm.operator()>("std::rotate(vector) (by 1/2)", std_rotate, 0.50); - // ranges::rotate - bm.operator()>("rng::rotate(vector)", std::ranges::rotate, 0.51); - bm.operator()>("rng::rotate(deque)", std::ranges::rotate, 0.51); - bm.operator()>("rng::rotate(list)", std::ranges::rotate, 0.51); -#if TEST_STD_VER >= 23 // vector::iterator is not std::permutable before C++23 bm.operator()>("rng::rotate(vector) (by 1/4)", std::ranges::rotate, 0.25); - bm.operator()>("rng::rotate(vector) (by 51%)", std::ranges::rotate, 0.51); -#endif + bm.operator()>("rng::rotate(vector) (by 1/3)", std::ranges::rotate, 0.33); + bm.operator()>("rng::rotate(vector) (by 1/2)", std::ranges::rotate, 0.50); + } + + // Benchmark {std,ranges}::rotate where we rotate a single element from the beginning to the end of the range. + { + auto bm = [](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::random(); }); + + auto pivot = std::next(c.begin()); + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + auto result = rotate(c.begin(), pivot, c.end()); + benchmark::DoNotOptimize(result); + } + }) + ->Arg(32) + ->Arg(50) // non power-of-two + ->Arg(1024) + ->Arg(8192); + }; + bm.operator()>("std::rotate(vector) (1 element forward)", std_rotate); + bm.operator()>("std::rotate(deque) (1 element forward)", std_rotate); + bm.operator()>("std::rotate(list) (1 element forward)", std_rotate); + bm.operator()>("rng::rotate(vector) (1 element forward)", std::ranges::rotate); + bm.operator()>("rng::rotate(deque) (1 element forward)", std::ranges::rotate); + bm.operator()>("rng::rotate(list) (1 element forward)", std::ranges::rotate); + + bm.operator()>("std::rotate(vector) (1 element forward)", std_rotate); + bm.operator()>("rng::rotate(vector) (1 element forward)", std::ranges::rotate); + } + + // Benchmark {std,ranges}::rotate where we rotate a single element from the end to the beginning of the range. + { + auto bm = [](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::random(); }); + + auto pivot = std::next(c.begin(), size - 1); + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + auto result = rotate(c.begin(), pivot, c.end()); + benchmark::DoNotOptimize(result); + } + }) + ->Arg(32) + ->Arg(50) // non power-of-two + ->Arg(1024) + ->Arg(8192); + }; + bm.operator()>("std::rotate(vector) (1 element backward)", std_rotate); + bm.operator()>("std::rotate(deque) (1 element backward)", std_rotate); + bm.operator()>("std::rotate(list) (1 element backward)", std_rotate); + bm.operator()>("rng::rotate(vector) (1 element backward)", std::ranges::rotate); + bm.operator()>("rng::rotate(deque) (1 element backward)", std::ranges::rotate); + bm.operator()>("rng::rotate(list) (1 element backward)", std::ranges::rotate); + + bm.operator()>("std::rotate(vector) (1 element backward)", std_rotate); + bm.operator()>("rng::rotate(vector) (1 element backward)", std::ranges::rotate); } benchmark::Initialize(&argc, argv); 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 -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::random(); }); - - std::vector 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::rotate_copy(vector)", std_rotate_copy); - bm>("std::rotate_copy(deque)", std_rotate_copy); - bm>("std::rotate_copy(list)", std_rotate_copy); + // {std,ranges}::rotate_copy(normal container) + { + auto bm = [](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::random(); }); + + std::vector out(size); - // ranges::rotate_copy - bm>("ranges::rotate_copy(vector)", ranges_rotate_copy); - bm>("ranges::rotate_copy(deque)", ranges_rotate_copy); - bm>("ranges::rotate_copy(list)", 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::rotate_copy(vector)", std_rotate_copy); + bm.operator()>("std::rotate_copy(deque)", std_rotate_copy); + bm.operator()>("std::rotate_copy(list)", std_rotate_copy); + bm.operator()>("rng::rotate_copy(vector)", std::ranges::rotate_copy); + bm.operator()>("rng::rotate_copy(deque)", std::ranges::rotate_copy); + bm.operator()>("rng::rotate_copy(list)", 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 -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::random(); }); - - std::vector 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::sample(vector)", std_sample); - bm>("std::sample(deque)", std_sample); - bm>("std::sample(list)", std_sample); + // {std,ranges}::sample(normal container) + { + auto bm = [](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::random(); }); + + std::vector out(size); + auto const n = size / 4; // sample 1/4 of the range + std::mt19937 rng; - // ranges::sample - bm>("ranges::sample(vector)", ranges_sample); - bm>("ranges::sample(deque)", ranges_sample); - bm>("ranges::sample(list)", 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::sample(vector)", std_sample); + bm.operator()>("std::sample(deque)", std_sample); + bm.operator()>("std::sample(list)", std_sample); + bm.operator()>("rng::sample(vector)", std::ranges::sample); + bm.operator()>("rng::sample(deque)", std::ranges::sample); + bm.operator()>("rng::sample(list)", 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 -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::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::shift_left(vector)", std_shift_left); - bm>("std::shift_left(deque)", std_shift_left); - bm>("std::shift_left(list)", std_shift_left); - - // ranges::shift_left not implemented yet + // std::shift_left(normal container) + { + auto bm = [](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::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::shift_left(vector)", std_shift_left); + bm.operator()>("std::shift_left(deque)", std_shift_left); + bm.operator()>("std::shift_left(list)", 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 -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::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::shift_right(vector)", std_shift_right); - bm>("std::shift_right(deque)", std_shift_right); - bm>("std::shift_right(list)", std_shift_right); - - // ranges::shift_right not implemented yet + // std::shift_right(normal container) + { + auto bm = [](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::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::shift_right(vector)", std_shift_right); + bm.operator()>("std::shift_right(deque)", std_shift_right); + bm.operator()>("std::shift_right(list)", 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 -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::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::shuffle(vector)", std_shuffle); - bm>("std::shuffle(deque)", std_shuffle); - - // ranges::shuffle - bm>("ranges::shuffle(vector)", ranges_shuffle); - bm>("ranges::shuffle(deque)", ranges_shuffle); + auto std_shuffle = [](auto first, auto last, auto& rng) { return std::shuffle(first, last, rng); }; + + // {std,ranges}::shuffle(normal container) + { + auto bm = [](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::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::shuffle(vector)", std_shuffle); + bm.operator()>("std::shuffle(deque)", std_shuffle); + bm.operator()>("rng::shuffle(vector)", std::ranges::shuffle); + bm.operator()>("rng::shuffle(deque)", 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 -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::random(); }); - std::generate_n(std::back_inserter(c2), size, [] { return Generate::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::swap_ranges(vector)", std_swap_ranges); - bm>("std::swap_ranges(deque)", std_swap_ranges); - bm>("std::swap_ranges(list)", std_swap_ranges); - // ranges::swap_ranges - bm>("ranges::swap_ranges(vector)", ranges_swap_ranges); - bm>("ranges::swap_ranges(deque)", ranges_swap_ranges); - bm>("ranges::swap_ranges(list)", ranges_swap_ranges); + // {std,ranges}::swap_ranges(normal container) + { + auto bm = [](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::random(); }); + std::generate_n(std::back_inserter(c2), size, [] { return Generate::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::swap_ranges(vector)", std_swap_ranges); + bm.operator()>("std::swap_ranges(deque)", std_swap_ranges); + bm.operator()>("std::swap_ranges(list)", std_swap_ranges); + bm.operator()>("rng::swap_ranges(vector)", std::ranges::swap_ranges); + bm.operator()>("rng::swap_ranges(deque)", std::ranges::swap_ranges); + bm.operator()>("rng::swap_ranges(list)", 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 -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::random(); }); - std::generate_n(std::back_inserter(c2), size, [] { return Generate::random(); }); - - std::vector 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::transform(vector, vector)", std_transform); - bm>("std::transform(deque, deque)", std_transform); - bm>("std::transform(list, list)", std_transform); + // {std,ranges}::transform(normal container, normal container) + { + auto bm = [](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::random(); }); + std::generate_n(std::back_inserter(c2), size, [] { return Generate::random(); }); + + std::vector out(size); - // ranges::transform - bm>("ranges::transform(vector, vector)", ranges_transform); - bm>("ranges::transform(deque, deque)", ranges_transform); - bm>("ranges::transform(list, list)", 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::transform(vector, vector)", std_transform); + bm.operator()>("std::transform(deque, deque)", std_transform); + bm.operator()>("std::transform(list, list)", std_transform); + bm.operator()>("rng::transform(vector, vector)", std::ranges::transform); + bm.operator()>("rng::transform(deque, deque)", std::ranges::transform); + bm.operator()>("rng::transform(list, list)", 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 -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::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 out(size); + // {std,ranges}::transform(normal container) + { + auto bm = [](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::random(); }); - auto f = [](auto& element) { - benchmark::DoNotOptimize(element); - return element; - }; + std::vector 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::transform(vector) (identity transform)", std_transform); - bm>("std::transform(deque) (identity transform)", std_transform); - bm>("std::transform(list) (identity transform)", std_transform); - - // ranges::transform - bm>("ranges::transform(vector) (identity transform)", ranges_transform); - bm>("ranges::transform(deque) (identity transform)", ranges_transform); - bm>("ranges::transform(list) (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::transform(vector) (identity transform)", std_transform); + bm.operator()>("std::transform(deque) (identity transform)", std_transform); + bm.operator()>("std::transform(list) (identity transform)", std_transform); + bm.operator()>("rng::transform(vector) (identity transform)", std::ranges::transform); + bm.operator()>("rng::transform(deque) (identity transform)", std::ranges::transform); + bm.operator()>("rng::transform(list) (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 -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::random(); - ValueType y = Generate::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 -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::random(); - ValueType y = Generate::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::unique(vector) (contiguous)", std_unique); - bm_sprinkled>("std::unique(vector) (sprinkled)", std_unique); - - bm_contiguous>("std::unique(deque) (contiguous)", std_unique); - bm_sprinkled>("std::unique(deque) (sprinkled)", std_unique); - - bm_contiguous>("std::unique(list) (contiguous)", std_unique); - bm_sprinkled>("std::unique(list) (sprinkled)", std_unique); - - // ranges::unique - bm_contiguous>("ranges::unique(vector) (contiguous)", ranges_unique); - bm_sprinkled>("ranges::unique(vector) (sprinkled)", ranges_unique); - - bm_contiguous>("ranges::unique(deque) (contiguous)", ranges_unique); - bm_sprinkled>("ranges::unique(deque) (sprinkled)", ranges_unique); - - bm_contiguous>("ranges::unique(list) (contiguous)", ranges_unique); - bm_sprinkled>("ranges::unique(list) (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 = [](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::random(); + ValueType y = Generate::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::unique(vector) (contiguous)", std_unique); + bm.operator()>("std::unique(deque) (contiguous)", std_unique); + bm.operator()>("std::unique(list) (contiguous)", std_unique); + bm.operator()>("rng::unique(vector) (contiguous)", std::ranges::unique); + bm.operator()>("rng::unique(deque) (contiguous)", std::ranges::unique); + bm.operator()>("rng::unique(list) (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 = [](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::random(); + ValueType y = Generate::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::unique(vector) (sprinkled)", std_unique); + bm.operator()>("std::unique(deque) (sprinkled)", std_unique); + bm.operator()>("std::unique(list) (sprinkled)", std_unique); + bm.operator()>("rng::unique(vector) (sprinkled)", std::ranges::unique); + bm.operator()>("rng::unique(deque) (sprinkled)", std::ranges::unique); + bm.operator()>("rng::unique(list) (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 -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::random(); - ValueType y = Generate::random(); - auto half = size / 2; - std::fill_n(std::fill_n(c.begin(), half, x), half, y); - - std::vector 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 -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::random(); - ValueType y = Generate::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 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::unique_copy(vector) (contiguous)", std_unique_copy); - bm_sprinkled>("std::unique_copy(vector) (sprinkled)", std_unique_copy); - - bm_contiguous>("std::unique_copy(deque) (contiguous)", std_unique_copy); - bm_sprinkled>("std::unique_copy(deque) (sprinkled)", std_unique_copy); - - bm_contiguous>("std::unique_copy(list) (contiguous)", std_unique_copy); - bm_sprinkled>("std::unique_copy(list) (sprinkled)", std_unique_copy); - - // ranges::unique_copy - bm_contiguous>("ranges::unique_copy(vector) (contiguous)", ranges_unique_copy); - bm_sprinkled>("ranges::unique_copy(vector) (sprinkled)", ranges_unique_copy); - - bm_contiguous>("ranges::unique_copy(deque) (contiguous)", ranges_unique_copy); - bm_sprinkled>("ranges::unique_copy(deque) (sprinkled)", ranges_unique_copy); - - bm_contiguous>("ranges::unique_copy(list) (contiguous)", ranges_unique_copy); - bm_sprinkled>("ranges::unique_copy(list) (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 = [](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::random(); + ValueType y = Generate::random(); + auto half = size / 2; + std::fill_n(std::fill_n(c.begin(), half, x), half, y); + + std::vector 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::unique_copy(vector) (contiguous)", std_unique_copy); + bm.operator()>("std::unique_copy(deque) (contiguous)", std_unique_copy); + bm.operator()>("std::unique_copy(list) (contiguous)", std_unique_copy); + bm.operator()>("rng::unique_copy(vector) (contiguous)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(deque) (contiguous)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(list) (contiguous)", std::ranges::unique_copy); + } + + // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique + // adjacent equal elements. + { + auto bm = [](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::random(); + ValueType y = Generate::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 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::unique_copy(vector) (sprinkled)", std_unique_copy); + bm.operator()>("std::unique_copy(deque) (sprinkled)", std_unique_copy); + bm.operator()>("std::unique_copy(list) (sprinkled)", std_unique_copy); + bm.operator()>("rng::unique_copy(vector) (sprinkled)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(deque) (sprinkled)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(list) (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 -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::random(); - ValueType y = Generate::random(); - auto half = size / 2; - std::fill_n(std::fill_n(c.begin(), half, x), half, y); - - std::vector 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 -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::random(); - ValueType y = Generate::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 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::unique_copy(vector, pred) (contiguous)", std_unique_copy); - bm_sprinkled>("std::unique_copy(vector, pred) (sprinkled)", std_unique_copy); - - bm_contiguous>("std::unique_copy(deque, pred) (contiguous)", std_unique_copy); - bm_sprinkled>("std::unique_copy(deque, pred) (sprinkled)", std_unique_copy); - bm_contiguous>("std::unique_copy(list, pred) (contiguous)", std_unique_copy); - bm_sprinkled>("std::unique_copy(list, pred) (sprinkled)", std_unique_copy); - - // ranges::unique_copy - bm_contiguous>("ranges::unique_copy(vector, pred) (contiguous)", ranges_unique_copy); - bm_sprinkled>("ranges::unique_copy(vector, pred) (sprinkled)", ranges_unique_copy); - - bm_contiguous>("ranges::unique_copy(deque, pred) (contiguous)", ranges_unique_copy); - bm_sprinkled>("ranges::unique_copy(deque, pred) (sprinkled)", ranges_unique_copy); - - bm_contiguous>("ranges::unique_copy(list, pred) (contiguous)", ranges_unique_copy); - bm_sprinkled>("ranges::unique_copy(list, pred) (sprinkled)", ranges_unique_copy); + // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the + // adjacent equal elements. + { + auto bm = [](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::random(); + ValueType y = Generate::random(); + auto half = size / 2; + std::fill_n(std::fill_n(c.begin(), half, x), half, y); + + std::vector 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::unique_copy(vector, pred) (contiguous)", std_unique_copy); + bm.operator()>("std::unique_copy(deque, pred) (contiguous)", std_unique_copy); + bm.operator()>("std::unique_copy(list, pred) (contiguous)", std_unique_copy); + bm.operator()>("rng::unique_copy(vector, pred) (contiguous)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(deque, pred) (contiguous)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(list, pred) (contiguous)", std::ranges::unique_copy); + } + + // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique + // adjacent equal elements. + { + auto bm = [](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::random(); + ValueType y = Generate::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 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::unique_copy(vector, pred) (sprinkled)", std_unique_copy); + bm.operator()>("std::unique_copy(deque, pred) (sprinkled)", std_unique_copy); + bm.operator()>("std::unique_copy(list, pred) (sprinkled)", std_unique_copy); + bm.operator()>("rng::unique_copy(vector, pred) (sprinkled)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(deque, pred) (sprinkled)", std::ranges::unique_copy); + bm.operator()>("rng::unique_copy(list, 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 -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::random(); - ValueType y = Generate::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 -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::random(); - ValueType y = Generate::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 = [](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::random(); + ValueType y = Generate::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::unique(vector, pred) (contiguous)", std_unique); + bm.operator()>("std::unique(deque, pred) (contiguous)", std_unique); + bm.operator()>("std::unique(list, pred) (contiguous)", std_unique); + bm.operator()>("rng::unique(vector, pred) (contiguous)", std::ranges::unique); + bm.operator()>("rng::unique(deque, pred) (contiguous)", std::ranges::unique); + bm.operator()>("rng::unique(list, 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 = [](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::random(); + ValueType y = Generate::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::unique(vector, pred) (contiguous)", std_unique); - bm_sprinkled>("std::unique(vector, pred) (sprinkled)", std_unique); - - bm_contiguous>("std::unique(deque, pred) (contiguous)", std_unique); - bm_sprinkled>("std::unique(deque, pred) (sprinkled)", std_unique); - - bm_contiguous>("std::unique(list, pred) (contiguous)", std_unique); - bm_sprinkled>("std::unique(list, pred) (sprinkled)", std_unique); - - // ranges::unique - bm_contiguous>("ranges::unique(vector, pred) (contiguous)", ranges_unique); - bm_sprinkled>("ranges::unique(vector, pred) (sprinkled)", ranges_unique); - - bm_contiguous>("ranges::unique(deque, pred) (contiguous)", ranges_unique); - bm_sprinkled>("ranges::unique(deque, pred) (sprinkled)", ranges_unique); - - bm_contiguous>("ranges::unique(list, pred) (contiguous)", ranges_unique); - bm_sprinkled>("ranges::unique(list, pred) (sprinkled)", ranges_unique); + bm.operator()>("std::unique(vector, pred) (sprinkled)", std_unique); + bm.operator()>("std::unique(deque, pred) (sprinkled)", std_unique); + bm.operator()>("std::unique(list, pred) (sprinkled)", std_unique); + bm.operator()>("rng::unique(vector, pred) (sprinkled)", std::ranges::unique); + bm.operator()>("rng::unique(deque, pred) (sprinkled)", std::ranges::unique); + bm.operator()>("rng::unique(list, pred) (sprinkled)", std::ranges::unique); + } benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); From 7bb00e6b258b1092400503106ab8f857f4fca24b Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 19 Feb 2025 16:36:59 -0500 Subject: [PATCH 04/15] 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 +-- .../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 ++-- 26 files changed, 112 insertions(+), 147 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 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 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::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::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 = [](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::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::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 = [](std::string name, auto move) { benchmark::RegisterBenchmark(name, [move](auto& st) { - std::size_t const n = st.range(0); - std::vector c1(n, true); - std::vector c2(n, false); + std::size_t const size = st.range(0); + std::vector c1(size, true); + std::vector c2(size, false); std::vector* in = &c1; std::vector* 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 = [](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::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::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 = [](std::string name, auto move_backward) { benchmark::RegisterBenchmark(name, [move_backward](auto& st) { - std::size_t const n = st.range(0); - std::vector c1(n, true); - std::vector c2(n, false); + std::size_t const size = st.range(0); + std::vector c1(size, true); + std::vector c2(size, false); std::vector* in = &c1; std::vector* 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 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 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 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 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::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 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_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::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 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 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(); From 285e315a37e24a70781e4d48b51aac88d4005683 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 20 Feb 2025 08:27:34 -0500 Subject: [PATCH 05/15] maybe_unused --- libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp | 2 +- .../benchmarks/algorithms/modifying/move_backward.bench.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp index 73e1a3881515f..8213c16b78e6b 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp @@ -61,7 +61,7 @@ int main(int argc, char** argv) { std::vector* in = &c1; std::vector* out = &c2; - for (auto _ : st) { + for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(in); benchmark::DoNotOptimize(out); auto first = Aligned ? in->begin() : in->begin() + 4; diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp index 0e6eea1b4d873..a5bfc75ec94e8 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp @@ -61,7 +61,7 @@ int main(int argc, char** argv) { std::vector* in = &c1; std::vector* out = &c2; - for (auto _ : st) { + for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(in); benchmark::DoNotOptimize(out); auto last = Aligned ? in->end() : in->end() - 4; From c355ebea4c41891cfd3cf208c02ab6fdf36d79fc Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Fri, 21 Feb 2025 12:27:48 -0500 Subject: [PATCH 06/15] Ensure uniqueness of elements when needed --- libcxx/test/benchmarks/GenerateInput.h | 9 +++++++++ .../benchmarks/algorithms/modifying/remove.bench.cpp | 4 ++-- .../algorithms/modifying/remove_copy.bench.cpp | 4 ++-- .../algorithms/modifying/remove_copy_if.bench.cpp | 4 ++-- .../benchmarks/algorithms/modifying/remove_if.bench.cpp | 4 ++-- .../benchmarks/algorithms/modifying/replace.bench.cpp | 8 ++++---- .../benchmarks/algorithms/modifying/replace_if.bench.cpp | 8 ++++---- .../benchmarks/algorithms/modifying/unique.bench.cpp | 4 ++-- .../algorithms/modifying/unique_copy.bench.cpp | 4 ++-- .../algorithms/modifying/unique_copy_pred.bench.cpp | 4 ++-- .../algorithms/modifying/unique_pred.bench.cpp | 4 ++-- 11 files changed, 33 insertions(+), 24 deletions(-) diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h index c87fd69162e9d..9f741a5d6c24c 100644 --- a/libcxx/test/benchmarks/GenerateInput.h +++ b/libcxx/test/benchmarks/GenerateInput.h @@ -204,4 +204,13 @@ struct Generate { } }; +template +T random_different_from(std::initializer_list others) { + T value; + do { + value = Generate::random(); + } while (std::ranges::contains(others, value)); + return value; +} + #endif // BENCHMARK_GENERATE_INPUT_H diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp index adec1d2292bcf..1067ecd9e8795 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp @@ -37,7 +37,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); for (std::size_t i = 0; i != BatchSize; ++i) { c[i] = Container(size); auto half = size / 2; @@ -87,7 +87,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto alternate = [&](auto out, auto n) { for (std::size_t i = 0; i != n; ++i) { *out++ = (i % 2 == 0 ? x : y); diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp index af9994c07cc22..ba290e4765219 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp @@ -35,7 +35,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); std::fill_n(std::back_inserter(c), size / 2, x); std::fill_n(std::back_inserter(c), size / 2, y); @@ -72,7 +72,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); for (std::size_t i = 0; i != size; ++i) { c.push_back(i % 2 == 0 ? x : y); } 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 e6fa7a0c1ea79..942a79f939138 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp @@ -35,7 +35,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); std::fill_n(std::back_inserter(c), size / 2, x); std::fill_n(std::back_inserter(c), size / 2, y); @@ -75,7 +75,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); for (std::size_t i = 0; i != size; ++i) { c.push_back(i % 2 == 0 ? x : y); } diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp index d5e185ef3ba9c..09f4b1495c897 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp @@ -37,7 +37,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); for (std::size_t i = 0; i != BatchSize; ++i) { c[i] = Container(size); auto half = size / 2; @@ -91,7 +91,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto alternate = [&](auto out, auto n) { for (std::size_t i = 0; i != n; ++i) { *out++ = (i % 2 == 0 ? x : y); diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp index e34f1e28c1459..e1bf5e20e99ea 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp @@ -36,8 +36,8 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); - ValueType z = Generate::random(); + ValueType y = random_different_from({x}); + ValueType z = random_different_from({x, y}); std::fill_n(std::back_inserter(c), size / 2, x); std::fill_n(std::back_inserter(c), size / 2, y); @@ -72,8 +72,8 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); - ValueType z = Generate::random(); + ValueType y = random_different_from({x}); + ValueType z = random_different_from({x, y}); for (std::size_t i = 0; i != size; ++i) { c.push_back(i % 2 == 0 ? x : y); } diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp index 1a51d3da4fc89..d7eab24b6d411 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp @@ -38,8 +38,8 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); - ValueType z = Generate::random(); + ValueType y = random_different_from({x}); + ValueType z = random_different_from({x, y}); std::fill_n(std::back_inserter(c), size / 2, x); std::fill_n(std::back_inserter(c), size / 2, y); @@ -77,8 +77,8 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; ValueType x = Generate::random(); - ValueType y = Generate::random(); - ValueType z = Generate::random(); + ValueType y = random_different_from({x}); + ValueType z = random_different_from({x, y}); for (std::size_t i = 0; i != size; ++i) { c.push_back(i % 2 == 0 ? x : y); } diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp index 2a334447f953b..477f1b5622c3e 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp @@ -37,7 +37,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); for (std::size_t i = 0; i != BatchSize; ++i) { c[i] = Container(size); auto half = size / 2; @@ -86,7 +86,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto alternate = [&](auto out, auto n) { for (std::size_t i = 0; i != n; i += 2) { *out++ = (i % 4 == 0 ? x : y); diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp index a8bd2ed327c2b..247e7d9c6e497 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp @@ -33,7 +33,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c(size); ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto half = size / 2; std::fill_n(std::fill_n(c.begin(), half, x), half, y); @@ -69,7 +69,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c(size); ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto alternate = [&](auto out, auto n) { for (std::size_t i = 0; i != n; i += 2) { *out++ = (i % 4 == 0 ? x : y); 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 4d29e16ce9e1e..72f94c196360e 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp @@ -35,7 +35,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c(size); ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto half = size / 2; std::fill_n(std::fill_n(c.begin(), half, x), half, y); @@ -77,7 +77,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c(size); ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto alternate = [&](auto out, auto n) { for (std::size_t i = 0; i != n; i += 2) { *out++ = (i % 4 == 0 ? x : y); diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp index 25f87e022023b..a333c965cee8f 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp @@ -37,7 +37,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); for (std::size_t i = 0; i != BatchSize; ++i) { c[i] = Container(size); auto half = size / 2; @@ -92,7 +92,7 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c[BatchSize]; ValueType x = Generate::random(); - ValueType y = Generate::random(); + ValueType y = random_different_from({x}); auto alternate = [&](auto out, auto n) { for (std::size_t i = 0; i != n; i += 2) { *out++ = (i % 4 == 0 ? x : y); From 8f05f2a3c683ec5fe71808b2fa3a66e3e68b8921 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Fri, 21 Feb 2025 16:38:03 -0500 Subject: [PATCH 07/15] C++20 friendly --- libcxx/test/benchmarks/GenerateInput.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h index 9f741a5d6c24c..9be76f55c2774 100644 --- a/libcxx/test/benchmarks/GenerateInput.h +++ b/libcxx/test/benchmarks/GenerateInput.h @@ -209,7 +209,7 @@ T random_different_from(std::initializer_list others) { T value; do { value = Generate::random(); - } while (std::ranges::contains(others, value)); + } while (std::find(others.begin(), others.end(), value) != others.end()); return value; } From 004e561a57f88e0c6cee0a602f75eac52f774af0 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 25 Feb 2025 10:06:05 -0500 Subject: [PATCH 08/15] Always fill with the same value --- .../test/benchmarks/algorithms/modifying/fill.bench.cpp | 8 ++------ .../test/benchmarks/algorithms/modifying/fill_n.bench.cpp | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp index 79f6619e2977f..7b3534969b247 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp @@ -32,15 +32,13 @@ int main(int argc, char** argv) { std::size_t const size = st.range(0); using ValueType = typename Container::value_type; ValueType x = Generate::random(); - ValueType y = Generate::random(); - Container c(size, y); + Container c(size, x); for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(x); fill(c.begin(), c.end(), x); benchmark::DoNotOptimize(c); - std::swap(x, y); } }) ->Arg(32) @@ -61,15 +59,13 @@ int main(int argc, char** argv) { benchmark::RegisterBenchmark(name, [fill](auto& st) { std::size_t const size = st.range(0); bool x = true; - bool y = false; - std::vector c(size, y); + std::vector c(size, x); for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(x); 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 505fbcbb2f442..700d109fdbc61 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp @@ -32,15 +32,13 @@ int main(int argc, char** argv) { std::size_t const size = st.range(0); using ValueType = typename Container::value_type; ValueType x = Generate::random(); - ValueType y = Generate::random(); - Container c(size, y); + Container c(size, x); for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(x); fill_n(c.begin(), size, x); benchmark::DoNotOptimize(c); - std::swap(x, y); } }) ->Arg(32) @@ -61,15 +59,13 @@ int main(int argc, char** argv) { benchmark::RegisterBenchmark(name, [fill_n](auto& st) { std::size_t const size = st.range(0); bool x = true; - bool y = false; - std::vector c(size, y); + std::vector c(size, x); for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(x); fill_n(c.begin(), size, x); benchmark::DoNotOptimize(c); - std::swap(x, y); } })->Range(64, 1 << 20); }; From 02b0178a14b7c3858d28c6a4d7bd9a6103f7f8db Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 25 Feb 2025 10:08:40 -0500 Subject: [PATCH 09/15] Don't take references in predicates --- .../benchmarks/algorithms/modifying/remove_copy_if.bench.cpp | 4 ++-- .../test/benchmarks/algorithms/modifying/remove_if.bench.cpp | 4 ++-- .../test/benchmarks/algorithms/modifying/replace_if.bench.cpp | 4 ++-- .../algorithms/modifying/transform.binary.bench.cpp | 2 +- .../benchmarks/algorithms/modifying/transform.unary.bench.cpp | 2 +- .../algorithms/modifying/unique_copy_pred.bench.cpp | 4 ++-- .../benchmarks/algorithms/modifying/unique_pred.bench.cpp | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) 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 942a79f939138..ca59f0fdb0338 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp @@ -44,7 +44,7 @@ int main(int argc, char** argv) { for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(out); - auto pred = [&x](auto& element) { + auto pred = [&x](auto element) { benchmark::DoNotOptimize(element); return element == x; }; @@ -85,7 +85,7 @@ int main(int argc, char** argv) { for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(out); - auto pred = [&](auto& element) { + auto pred = [&](auto element) { benchmark::DoNotOptimize(element); return element == x; }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp index 09f4b1495c897..23ea0a4824242 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp @@ -44,7 +44,7 @@ int main(int argc, char** argv) { std::fill_n(std::fill_n(c[i].begin(), half, x), half, y); } - auto pred = [&](auto& element) { + auto pred = [&](auto element) { benchmark::DoNotOptimize(element); return element == x; }; @@ -102,7 +102,7 @@ int main(int argc, char** argv) { alternate(c[i].begin(), size); } - auto pred = [&](auto& element) { + auto pred = [&](auto element) { benchmark::DoNotOptimize(element); return element == x; }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp index d7eab24b6d411..ecd46dae01089 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp @@ -46,7 +46,7 @@ int main(int argc, char** argv) { for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(z); - auto pred = [&x](auto& element) { + auto pred = [&x](auto element) { benchmark::DoNotOptimize(element); return element == x; }; @@ -86,7 +86,7 @@ int main(int argc, char** argv) { for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); benchmark::DoNotOptimize(z); - auto pred = [&x](auto& element) { + auto pred = [&x](auto element) { benchmark::DoNotOptimize(element); return element == x; }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp index dd5e3783e6f13..cb6cfceee5bc4 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp @@ -38,7 +38,7 @@ int main(int argc, char** argv) { std::vector out(size); - auto f = [](auto& x, auto& y) { + auto f = [](auto x, auto y) { benchmark::DoNotOptimize(x); benchmark::DoNotOptimize(y); return x + y; diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp index e36a5f96c4e6f..db02fb67556b9 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp @@ -35,7 +35,7 @@ int main(int argc, char** argv) { std::vector out(size); - auto f = [](auto& element) { + auto f = [](auto element) { benchmark::DoNotOptimize(element); return element; }; 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 72f94c196360e..91031ef884611 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp @@ -41,7 +41,7 @@ int main(int argc, char** argv) { std::vector out(size); - auto pred = [](auto& a, auto& b) { + auto pred = [](auto a, auto b) { benchmark::DoNotOptimize(a); benchmark::DoNotOptimize(b); return a == b; @@ -88,7 +88,7 @@ int main(int argc, char** argv) { std::vector out(size); - auto pred = [](auto& a, auto& b) { + auto pred = [](auto a, auto b) { benchmark::DoNotOptimize(a); benchmark::DoNotOptimize(b); return a == b; diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp index a333c965cee8f..1b0ea26c6b7f5 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp @@ -44,7 +44,7 @@ int main(int argc, char** argv) { std::fill_n(std::fill_n(c[i].begin(), half, x), half, y); } - auto pred = [](auto& a, auto& b) { + auto pred = [](auto a, auto b) { benchmark::DoNotOptimize(a); benchmark::DoNotOptimize(b); return a == b; @@ -104,7 +104,7 @@ int main(int argc, char** argv) { alternate(c[i].begin(), size); } - auto pred = [](auto& a, auto& b) { + auto pred = [](auto a, auto b) { benchmark::DoNotOptimize(a); benchmark::DoNotOptimize(b); return a == b; From 935af6678e431168db44bac8c7d503743cbcc986 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 25 Feb 2025 10:28:26 -0500 Subject: [PATCH 10/15] Merge predicated version of the algorithms --- .../algorithms/modifying/remove.bench.cpp | 34 ++++- .../modifying/remove_copy.bench.cpp | 34 ++++- .../modifying/remove_copy_if.bench.cpp | 112 -------------- .../algorithms/modifying/remove_if.bench.cpp | 140 ----------------- .../algorithms/modifying/replace.bench.cpp | 34 ++++- .../algorithms/modifying/replace_if.bench.cpp | 114 -------------- .../algorithms/modifying/unique.bench.cpp | 34 ++++- .../modifying/unique_copy.bench.cpp | 34 ++++- .../modifying/unique_copy_pred.bench.cpp | 120 --------------- .../modifying/unique_pred.bench.cpp | 143 ------------------ 10 files changed, 163 insertions(+), 636 deletions(-) delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp index 1067ecd9e8795..07e8f834a8639 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp @@ -20,9 +20,21 @@ #include "../../GenerateInput.h" int main(int argc, char** argv) { - auto std_remove = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); }; + auto std_remove = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); }; + auto std_remove_if = [](auto first, auto last, auto const& value) { + return std::remove_if(first, last, [&](auto element) { + benchmark::DoNotOptimize(element); + return element == value; + }); + }; + auto ranges_remove_if = [](auto first, auto last, auto const& value) { + return std::ranges::remove_if(first, last, [&](auto element) { + benchmark::DoNotOptimize(element); + return element == value; + }); + }; - // Benchmark {std,ranges}::remove on a sequence of the form xxxxxxxxxxyyyyyyyyyy + // Benchmark {std,ranges}::{remove,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 @@ -64,12 +76,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::remove bm.operator()>("std::remove(vector) (prefix)", std_remove); bm.operator()>("std::remove(deque) (prefix)", std_remove); bm.operator()>("std::remove(list) (prefix)", std_remove); bm.operator()>("rng::remove(vector) (prefix)", std::ranges::remove); bm.operator()>("rng::remove(deque) (prefix)", std::ranges::remove); bm.operator()>("rng::remove(list) (prefix)", std::ranges::remove); + + // {std,ranges}::remove_if + bm.operator()>("std::remove_if(vector) (prefix)", std_remove_if); + bm.operator()>("std::remove_if(deque) (prefix)", std_remove_if); + bm.operator()>("std::remove_if(list) (prefix)", std_remove_if); + bm.operator()>("rng::remove_if(vector) (prefix)", ranges_remove_if); + bm.operator()>("rng::remove_if(deque) (prefix)", ranges_remove_if); + bm.operator()>("rng::remove_if(list) (prefix)", ranges_remove_if); } // Benchmark {std,ranges}::remove on a sequence of the form xyxyxyxyxyxyxyxyxyxy @@ -117,12 +138,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::remove bm.operator()>("std::remove(vector) (sprinkled)", std_remove); bm.operator()>("std::remove(deque) (sprinkled)", std_remove); bm.operator()>("std::remove(list) (sprinkled)", std_remove); bm.operator()>("rng::remove(vector) (sprinkled)", std::ranges::remove); bm.operator()>("rng::remove(deque) (sprinkled)", std::ranges::remove); bm.operator()>("rng::remove(list) (sprinkled)", std::ranges::remove); + + // {std,ranges}::remove_if + bm.operator()>("std::remove_if(vector) (sprinkled)", std_remove_if); + bm.operator()>("std::remove_if(deque) (sprinkled)", std_remove_if); + bm.operator()>("std::remove_if(list) (sprinkled)", std_remove_if); + bm.operator()>("rng::remove_if(vector) (sprinkled)", ranges_remove_if); + bm.operator()>("rng::remove_if(deque) (sprinkled)", ranges_remove_if); + bm.operator()>("rng::remove_if(list) (sprinkled)", ranges_remove_if); } benchmark::Initialize(&argc, argv); diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp index ba290e4765219..b0bc58e8a7a2f 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp @@ -23,8 +23,20 @@ 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 std_remove_copy_if = [](auto first, auto last, auto out, auto const& value) { + return std::remove_copy_if(first, last, out, [&](auto element) { + benchmark::DoNotOptimize(element); + return element == value; + }); + }; + auto ranges_remove_copy_if = [](auto first, auto last, auto out, auto const& value) { + return std::ranges::remove_copy_if(first, last, out, [&](auto element) { + benchmark::DoNotOptimize(element); + return element == value; + }); + }; - // Benchmark {std,ranges}::remove_copy on a sequence of the form xxxxxxxxxxyyyyyyyyyy + // Benchmark {std,ranges}::{remove_copy,remove_copy_if} on a sequence of the form xxxxxxxxxxyyyyyyyyyy // where we remove the prefix of x's from the sequence. { auto bm = [](std::string name, auto remove_copy) { @@ -53,15 +65,24 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::remove_copy bm.operator()>("std::remove_copy(vector) (prefix)", std_remove_copy); bm.operator()>("std::remove_copy(deque) (prefix)", std_remove_copy); bm.operator()>("std::remove_copy(list) (prefix)", std_remove_copy); bm.operator()>("rng::remove_copy(vector) (prefix)", std::ranges::remove_copy); bm.operator()>("rng::remove_copy(deque) (prefix)", std::ranges::remove_copy); bm.operator()>("rng::remove_copy(list) (prefix)", std::ranges::remove_copy); + + // {std,ranges}::remove_copy_if + bm.operator()>("std::remove_copy_if(vector) (prefix)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(deque) (prefix)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(list) (prefix)", std_remove_copy_if); + bm.operator()>("rng::remove_copy_if(vector) (prefix)", ranges_remove_copy_if); + bm.operator()>("rng::remove_copy_if(deque) (prefix)", ranges_remove_copy_if); + bm.operator()>("rng::remove_copy_if(list) (prefix)", ranges_remove_copy_if); } - // Benchmark {std,ranges}::remove_copy on a sequence of the form xyxyxyxyxyxyxyxyxyxy + // Benchmark {std,ranges}::{remove_copy,remove_copy_if} on a sequence of the form xyxyxyxyxyxyxyxyxyxy // where we remove the x's from the sequence. { auto bm = [](std::string name, auto remove_copy) { @@ -91,12 +112,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::remove_copy bm.operator()>("std::remove_copy(vector) (sprinkled)", std_remove_copy); bm.operator()>("std::remove_copy(deque) (sprinkled)", std_remove_copy); bm.operator()>("std::remove_copy(list) (sprinkled)", std_remove_copy); bm.operator()>("rng::remove_copy(vector) (sprinkled)", std::ranges::remove_copy); bm.operator()>("rng::remove_copy(deque) (sprinkled)", std::ranges::remove_copy); bm.operator()>("rng::remove_copy(list) (sprinkled)", std::ranges::remove_copy); + + // {std,ranges}::remove_copy_if + bm.operator()>("std::remove_copy_if(vector) (sprinkled)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(deque) (sprinkled)", std_remove_copy_if); + bm.operator()>("std::remove_copy_if(list) (sprinkled)", std_remove_copy_if); + bm.operator()>("rng::remove_copy_if(vector) (sprinkled)", ranges_remove_copy_if); + bm.operator()>("rng::remove_copy_if(deque) (sprinkled)", ranges_remove_copy_if); + bm.operator()>("rng::remove_copy_if(list) (sprinkled)", ranges_remove_copy_if); } benchmark::Initialize(&argc, argv); diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp deleted file mode 100644 index ca59f0fdb0338..0000000000000 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark/benchmark.h" -#include "../../GenerateInput.h" - -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); - }; - - // 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 = [](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::random(); - ValueType y = random_different_from({x}); - std::fill_n(std::back_inserter(c), size / 2, x); - std::fill_n(std::back_inserter(c), size / 2, y); - - std::vector out(size); - - for ([[maybe_unused]] auto _ : st) { - benchmark::DoNotOptimize(c); - benchmark::DoNotOptimize(out); - 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) - ->Arg(1024) - ->Arg(8192); - }; - bm.operator()>("std::remove_copy_if(vector) (prefix)", std_remove_copy_if); - bm.operator()>("std::remove_copy_if(deque) (prefix)", std_remove_copy_if); - bm.operator()>("std::remove_copy_if(list) (prefix)", std_remove_copy_if); - bm.operator()>("rng::remove_copy_if(vector) (prefix)", std::ranges::remove_copy_if); - bm.operator()>("rng::remove_copy_if(deque) (prefix)", std::ranges::remove_copy_if); - bm.operator()>("rng::remove_copy_if(list) (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 = [](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::random(); - ValueType y = random_different_from({x}); - for (std::size_t i = 0; i != size; ++i) { - c.push_back(i % 2 == 0 ? x : y); - } - - std::vector out(size); - - for ([[maybe_unused]] auto _ : st) { - benchmark::DoNotOptimize(c); - benchmark::DoNotOptimize(out); - 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) - ->Arg(1024) - ->Arg(8192); - }; - bm.operator()>("std::remove_copy_if(vector) (sprinkled)", std_remove_copy_if); - bm.operator()>("std::remove_copy_if(deque) (sprinkled)", std_remove_copy_if); - bm.operator()>("std::remove_copy_if(list) (sprinkled)", std_remove_copy_if); - bm.operator()>("rng::remove_copy_if(vector) (sprinkled)", std::ranges::remove_copy_if); - bm.operator()>("rng::remove_copy_if(deque) (sprinkled)", std::ranges::remove_copy_if); - bm.operator()>("rng::remove_copy_if(list) (sprinkled)", std::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 deleted file mode 100644 index 23ea0a4824242..0000000000000 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp +++ /dev/null @@ -1,140 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark/benchmark.h" -#include "../../GenerateInput.h" - -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 = [](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::random(); - ValueType y = random_different_from({x}); - 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) { - benchmark::DoNotOptimize(c[i]); - auto result = remove_if(c[i].begin(), c[i].end(), pred); - benchmark::DoNotOptimize(result); - } - - 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::remove_if(vector) (prefix)", std_remove_if); - bm.operator()>("std::remove_if(deque) (prefix)", std_remove_if); - bm.operator()>("std::remove_if(list) (prefix)", std_remove_if); - bm.operator()>("rng::remove_if(vector) (prefix)", std::ranges::remove_if); - bm.operator()>("rng::remove_if(deque) (prefix)", std::ranges::remove_if); - bm.operator()>("rng::remove_if(list) (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 = [](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::random(); - ValueType y = random_different_from({x}); - 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) { - benchmark::DoNotOptimize(c[i]); - auto result = remove_if(c[i].begin(), c[i].end(), pred); - benchmark::DoNotOptimize(result); - } - - 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::remove_if(vector) (sprinkled)", std_remove_if); - bm.operator()>("std::remove_if(deque) (sprinkled)", std_remove_if); - bm.operator()>("std::remove_if(list) (sprinkled)", std_remove_if); - bm.operator()>("rng::remove_if(vector) (sprinkled)", std::ranges::remove_if); - bm.operator()>("rng::remove_if(deque) (sprinkled)", std::ranges::remove_if); - bm.operator()>("rng::remove_if(list) (sprinkled)", std::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 index e1bf5e20e99ea..5df7aa1fbbc04 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp @@ -20,7 +20,21 @@ #include "../../GenerateInput.h" 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 std_replace = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); }; + auto std_replace_if = [](auto first, auto last, auto old, auto new_) { + auto pred = [&](auto element) { + benchmark::DoNotOptimize(element); + return element == old; + }; + return std::replace_if(first, last, pred, new_); + }; + auto ranges_replace_if = [](auto first, auto last, auto old, auto new_) { + auto pred = [&](auto element) { + benchmark::DoNotOptimize(element); + return element == old; + }; + return std::ranges::replace_if(first, last, pred, new_); + }; // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace // into zzzzzzzzzzzyyyyyyyyyy and then back. @@ -54,12 +68,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::replace bm.operator()>("std::replace(vector) (prefix)", std_replace); bm.operator()>("std::replace(deque) (prefix)", std_replace); bm.operator()>("std::replace(list) (prefix)", std_replace); bm.operator()>("rng::replace(vector) (prefix)", std::ranges::replace); bm.operator()>("rng::replace(deque) (prefix)", std::ranges::replace); bm.operator()>("rng::replace(list) (prefix)", std::ranges::replace); + + // {std,ranges}::replace_if + bm.operator()>("std::replace_if(vector) (prefix)", std_replace_if); + bm.operator()>("std::replace_if(deque) (prefix)", std_replace_if); + bm.operator()>("std::replace_if(list) (prefix)", std_replace_if); + bm.operator()>("rng::replace_if(vector) (prefix)", ranges_replace_if); + bm.operator()>("rng::replace_if(deque) (prefix)", ranges_replace_if); + bm.operator()>("rng::replace_if(list) (prefix)", ranges_replace_if); } // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy. @@ -91,12 +114,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::replace bm.operator()>("std::replace(vector) (sprinkled)", std_replace); bm.operator()>("std::replace(deque) (sprinkled)", std_replace); bm.operator()>("std::replace(list) (sprinkled)", std_replace); bm.operator()>("rng::replace(vector) (sprinkled)", std::ranges::replace); bm.operator()>("rng::replace(deque) (sprinkled)", std::ranges::replace); bm.operator()>("rng::replace(list) (sprinkled)", std::ranges::replace); + + // {std,ranges}::replace_if + bm.operator()>("std::replace_if(vector) (sprinkled)", std_replace_if); + bm.operator()>("std::replace_if(deque) (sprinkled)", std_replace_if); + bm.operator()>("std::replace_if(list) (sprinkled)", std_replace_if); + bm.operator()>("rng::replace_if(vector) (sprinkled)", ranges_replace_if); + bm.operator()>("rng::replace_if(deque) (sprinkled)", ranges_replace_if); + bm.operator()>("rng::replace_if(list) (sprinkled)", ranges_replace_if); } benchmark::Initialize(&argc, argv); diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp deleted file mode 100644 index ecd46dae01089..0000000000000 --- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp +++ /dev/null @@ -1,114 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark/benchmark.h" -#include "../../GenerateInput.h" - -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_); - }; - - // 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 = [](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::random(); - ValueType y = random_different_from({x}); - ValueType z = random_different_from({x, y}); - 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) { - 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); - benchmark::DoNotOptimize(c); - std::swap(x, z); - } - }) - ->Arg(32) - ->Arg(1024) - ->Arg(8192); - }; - bm.operator()>("std::replace_if(vector) (prefix)", std_replace_if); - bm.operator()>("std::replace_if(deque) (prefix)", std_replace_if); - bm.operator()>("std::replace_if(list) (prefix)", std_replace_if); - bm.operator()>("rng::replace_if(vector) (prefix)", std::ranges::replace_if); - bm.operator()>("rng::replace_if(deque) (prefix)", std::ranges::replace_if); - bm.operator()>("rng::replace_if(list) (prefix)", std::ranges::replace_if); - } - - // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy. - { - auto bm = [](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::random(); - ValueType y = random_different_from({x}); - ValueType z = random_different_from({x, y}); - for (std::size_t i = 0; i != size; ++i) { - c.push_back(i % 2 == 0 ? x : y); - } - - for ([[maybe_unused]] auto _ : st) { - benchmark::DoNotOptimize(c); - benchmark::DoNotOptimize(z); - auto pred = [&x](auto element) { - benchmark::DoNotOptimize(element); - return element == x; - }; - replace_if(c.begin(), c.end(), pred, z); - benchmark::DoNotOptimize(c); - std::swap(x, z); - } - }) - ->Arg(32) - ->Arg(1024) - ->Arg(8192); - }; - bm.operator()>("std::replace_if(vector) (sprinkled)", std_replace_if); - bm.operator()>("std::replace_if(deque) (sprinkled)", std_replace_if); - bm.operator()>("std::replace_if(list) (sprinkled)", std_replace_if); - bm.operator()>("rng::replace_if(vector) (sprinkled)", std::ranges::replace_if); - bm.operator()>("rng::replace_if(deque) (sprinkled)", std::ranges::replace_if); - bm.operator()>("rng::replace_if(list) (sprinkled)", std::ranges::replace_if); - } - - 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 index 477f1b5622c3e..4ba4106f35cc9 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp @@ -20,7 +20,21 @@ #include "../../GenerateInput.h" int main(int argc, char** argv) { - auto std_unique = [](auto first, auto last) { return std::unique(first, last); }; + auto std_unique = [](auto first, auto last) { return std::unique(first, last); }; + auto std_unique_pred = [](auto first, auto last) { + return std::unique(first, last, [](auto a, auto b) { + benchmark::DoNotOptimize(a); + benchmark::DoNotOptimize(b); + return a == b; + }); + }; + auto ranges_unique_pred = [](auto first, auto last) { + return std::ranges::unique(first, last, [](auto a, auto b) { + benchmark::DoNotOptimize(a); + benchmark::DoNotOptimize(b); + return a == b; + }); + }; // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the // adjacent equal elements. @@ -63,12 +77,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::unique(it, it) bm.operator()>("std::unique(vector) (contiguous)", std_unique); bm.operator()>("std::unique(deque) (contiguous)", std_unique); bm.operator()>("std::unique(list) (contiguous)", std_unique); bm.operator()>("rng::unique(vector) (contiguous)", std::ranges::unique); bm.operator()>("rng::unique(deque) (contiguous)", std::ranges::unique); bm.operator()>("rng::unique(list) (contiguous)", std::ranges::unique); + + // {std,ranges}::unique(it, it, pred) + bm.operator()>("std::unique(vector, pred) (contiguous)", std_unique_pred); + bm.operator()>("std::unique(deque, pred) (contiguous)", std_unique_pred); + bm.operator()>("std::unique(list, pred) (contiguous)", std_unique_pred); + bm.operator()>("rng::unique(vector, pred) (contiguous)", ranges_unique_pred); + bm.operator()>("rng::unique(deque, pred) (contiguous)", ranges_unique_pred); + bm.operator()>("rng::unique(list, pred) (contiguous)", ranges_unique_pred); } // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique @@ -116,12 +139,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::unique(it, it) bm.operator()>("std::unique(vector) (sprinkled)", std_unique); bm.operator()>("std::unique(deque) (sprinkled)", std_unique); bm.operator()>("std::unique(list) (sprinkled)", std_unique); bm.operator()>("rng::unique(vector) (sprinkled)", std::ranges::unique); bm.operator()>("rng::unique(deque) (sprinkled)", std::ranges::unique); bm.operator()>("rng::unique(list) (sprinkled)", std::ranges::unique); + + // {std,ranges}::unique(it, it, pred) + bm.operator()>("std::unique(vector, pred) (sprinkled)", std_unique_pred); + bm.operator()>("std::unique(deque, pred) (sprinkled)", std_unique_pred); + bm.operator()>("std::unique(list, pred) (sprinkled)", std_unique_pred); + bm.operator()>("rng::unique(vector, pred) (sprinkled)", ranges_unique_pred); + bm.operator()>("rng::unique(deque, pred) (sprinkled)", ranges_unique_pred); + bm.operator()>("rng::unique(list, pred) (sprinkled)", ranges_unique_pred); } benchmark::Initialize(&argc, argv); diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp index 247e7d9c6e497..9aa96316d6e33 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp @@ -20,7 +20,21 @@ #include "../../GenerateInput.h" int main(int argc, char** argv) { - auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); }; + auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); }; + auto std_unique_copy_pred = [](auto first, auto last, auto out) { + return std::unique_copy(first, last, out, [](auto a, auto b) { + benchmark::DoNotOptimize(a); + benchmark::DoNotOptimize(b); + return a == b; + }); + }; + auto ranges_unique_copy_pred = [](auto first, auto last, auto out) { + return std::ranges::unique_copy(first, last, out, [](auto a, auto b) { + benchmark::DoNotOptimize(a); + benchmark::DoNotOptimize(b); + return a == b; + }); + }; // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the // adjacent equal elements. @@ -50,12 +64,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::unique_copy(it, it, out) bm.operator()>("std::unique_copy(vector) (contiguous)", std_unique_copy); bm.operator()>("std::unique_copy(deque) (contiguous)", std_unique_copy); bm.operator()>("std::unique_copy(list) (contiguous)", std_unique_copy); bm.operator()>("rng::unique_copy(vector) (contiguous)", std::ranges::unique_copy); bm.operator()>("rng::unique_copy(deque) (contiguous)", std::ranges::unique_copy); bm.operator()>("rng::unique_copy(list) (contiguous)", std::ranges::unique_copy); + + // {std,ranges}::unique_copy(it, it, out, pred) + bm.operator()>("std::unique_copy(vector, pred) (contiguous)", std_unique_copy_pred); + bm.operator()>("std::unique_copy(deque, pred) (contiguous)", std_unique_copy_pred); + bm.operator()>("std::unique_copy(list, pred) (contiguous)", std_unique_copy_pred); + bm.operator()>("rng::unique_copy(vector, pred) (contiguous)", ranges_unique_copy_pred); + bm.operator()>("rng::unique_copy(deque, pred) (contiguous)", ranges_unique_copy_pred); + bm.operator()>("rng::unique_copy(list, pred) (contiguous)", ranges_unique_copy_pred); } // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique @@ -91,12 +114,21 @@ int main(int argc, char** argv) { ->Arg(1024) ->Arg(8192); }; + // {std,ranges}::unique_copy(it, it, out) bm.operator()>("std::unique_copy(vector) (sprinkled)", std_unique_copy); bm.operator()>("std::unique_copy(deque) (sprinkled)", std_unique_copy); bm.operator()>("std::unique_copy(list) (sprinkled)", std_unique_copy); bm.operator()>("rng::unique_copy(vector) (sprinkled)", std::ranges::unique_copy); bm.operator()>("rng::unique_copy(deque) (sprinkled)", std::ranges::unique_copy); bm.operator()>("rng::unique_copy(list) (sprinkled)", std::ranges::unique_copy); + + // {std,ranges}::unique_copy(it, it, out, pred) + bm.operator()>("std::unique_copy(vector, pred) (sprinkled)", std_unique_copy_pred); + bm.operator()>("std::unique_copy(deque, pred) (sprinkled)", std_unique_copy_pred); + bm.operator()>("std::unique_copy(list, pred) (sprinkled)", std_unique_copy_pred); + bm.operator()>("rng::unique_copy(vector, pred) (sprinkled)", ranges_unique_copy_pred); + bm.operator()>("rng::unique_copy(deque, pred) (sprinkled)", ranges_unique_copy_pred); + bm.operator()>("rng::unique_copy(list, pred) (sprinkled)", ranges_unique_copy_pred); } benchmark::Initialize(&argc, argv); diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp deleted file mode 100644 index 91031ef884611..0000000000000 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp +++ /dev/null @@ -1,120 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark/benchmark.h" -#include "../../GenerateInput.h" - -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); - }; - - // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the - // adjacent equal elements. - { - auto bm = [](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::random(); - ValueType y = random_different_from({x}); - auto half = size / 2; - std::fill_n(std::fill_n(c.begin(), half, x), half, y); - - std::vector out(size); - - auto pred = [](auto a, auto b) { - benchmark::DoNotOptimize(a); - benchmark::DoNotOptimize(b); - return a == b; - }; - - 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); - } - }) - ->Arg(32) - ->Arg(1024) - ->Arg(8192); - }; - bm.operator()>("std::unique_copy(vector, pred) (contiguous)", std_unique_copy); - bm.operator()>("std::unique_copy(deque, pred) (contiguous)", std_unique_copy); - bm.operator()>("std::unique_copy(list, pred) (contiguous)", std_unique_copy); - bm.operator()>("rng::unique_copy(vector, pred) (contiguous)", std::ranges::unique_copy); - bm.operator()>("rng::unique_copy(deque, pred) (contiguous)", std::ranges::unique_copy); - bm.operator()>("rng::unique_copy(list, pred) (contiguous)", std::ranges::unique_copy); - } - - // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique - // adjacent equal elements. - { - auto bm = [](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::random(); - ValueType y = random_different_from({x}); - 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 out(size); - - auto pred = [](auto a, auto b) { - benchmark::DoNotOptimize(a); - benchmark::DoNotOptimize(b); - return a == b; - }; - - 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); - } - }) - ->Arg(32) - ->Arg(1024) - ->Arg(8192); - }; - bm.operator()>("std::unique_copy(vector, pred) (sprinkled)", std_unique_copy); - bm.operator()>("std::unique_copy(deque, pred) (sprinkled)", std_unique_copy); - bm.operator()>("std::unique_copy(list, pred) (sprinkled)", std_unique_copy); - bm.operator()>("rng::unique_copy(vector, pred) (sprinkled)", std::ranges::unique_copy); - bm.operator()>("rng::unique_copy(deque, pred) (sprinkled)", std::ranges::unique_copy); - bm.operator()>("rng::unique_copy(list, pred) (sprinkled)", std::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 deleted file mode 100644 index 1b0ea26c6b7f5..0000000000000 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp +++ /dev/null @@ -1,143 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark/benchmark.h" -#include "../../GenerateInput.h" - -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 = [](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::random(); - ValueType y = random_different_from({x}); - 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) { - benchmark::DoNotOptimize(c[i]); - auto result = unique(c[i].begin(), c[i].end(), pred); - benchmark::DoNotOptimize(result); - } - - 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::unique(vector, pred) (contiguous)", std_unique); - bm.operator()>("std::unique(deque, pred) (contiguous)", std_unique); - bm.operator()>("std::unique(list, pred) (contiguous)", std_unique); - bm.operator()>("rng::unique(vector, pred) (contiguous)", std::ranges::unique); - bm.operator()>("rng::unique(deque, pred) (contiguous)", std::ranges::unique); - bm.operator()>("rng::unique(list, 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 = [](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::random(); - ValueType y = random_different_from({x}); - 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) { - benchmark::DoNotOptimize(c[i]); - auto result = unique(c[i].begin(), c[i].end(), pred); - benchmark::DoNotOptimize(result); - } - - 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::unique(vector, pred) (sprinkled)", std_unique); - bm.operator()>("std::unique(deque, pred) (sprinkled)", std_unique); - bm.operator()>("std::unique(list, pred) (sprinkled)", std_unique); - bm.operator()>("rng::unique(vector, pred) (sprinkled)", std::ranges::unique); - bm.operator()>("rng::unique(deque, pred) (sprinkled)", std::ranges::unique); - bm.operator()>("rng::unique(list, pred) (sprinkled)", std::ranges::unique); - } - - benchmark::Initialize(&argc, argv); - benchmark::RunSpecifiedBenchmarks(); - benchmark::Shutdown(); - return 0; -} From 66f34f10874f8bacb369f81d52bfb57ffde545d8 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 25 Feb 2025 10:38:19 -0500 Subject: [PATCH 11/15] Simplify how we generate alternating sequences --- .../algorithms/modifying/remove.bench.cpp | 29 ++++++++------- .../algorithms/modifying/unique.bench.cpp | 36 +++++++++++-------- .../modifying/unique_copy.bench.cpp | 18 ++++++---- 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp index 07e8f834a8639..f0713dc7f9720 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp @@ -48,12 +48,15 @@ int main(int argc, char** argv) { constexpr std::size_t BatchSize = 10; using ValueType = typename Container::value_type; Container c[BatchSize]; - ValueType x = Generate::random(); - ValueType y = random_different_from({x}); + ValueType x = Generate::random(); + ValueType y = random_different_from({x}); + auto populate = [&](Container& cont) { + auto half = cont.size() / 2; + std::fill_n(std::fill_n(cont.begin(), half, x), half, y); + }; 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); + c[i] = Container(size); + populate(c[i]); } while (st.KeepRunningBatch(BatchSize)) { @@ -66,8 +69,7 @@ int main(int argc, char** argv) { 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); + populate(c[i]); } st.ResumeTiming(); } @@ -107,16 +109,17 @@ int main(int argc, char** argv) { constexpr std::size_t BatchSize = 10; using ValueType = typename Container::value_type; Container c[BatchSize]; - ValueType x = Generate::random(); - ValueType y = random_different_from({x}); - auto alternate = [&](auto out, auto n) { - for (std::size_t i = 0; i != n; ++i) { + ValueType x = Generate::random(); + ValueType y = random_different_from({x}); + auto populate = [&](Container& cont) { + auto out = cont.begin(); + for (std::size_t i = 0; i != cont.size(); ++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); + populate(c[i]); } while (st.KeepRunningBatch(BatchSize)) { @@ -129,7 +132,7 @@ int main(int argc, char** argv) { st.PauseTiming(); for (std::size_t i = 0; i != BatchSize; ++i) { - alternate(c[i].begin(), size); + populate(c[i]); } st.ResumeTiming(); } diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp index 4ba4106f35cc9..baec1fc8187d9 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp @@ -50,12 +50,15 @@ int main(int argc, char** argv) { constexpr std::size_t BatchSize = 10; using ValueType = typename Container::value_type; Container c[BatchSize]; - ValueType x = Generate::random(); - ValueType y = random_different_from({x}); + ValueType x = Generate::random(); + ValueType y = random_different_from({x}); + auto populate = [&](Container& cont) { + auto half = cont.size() / 2; + std::fill_n(std::fill_n(cont.begin(), half, x), half, y); + }; 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); + c[i] = Container(size); + populate(c[i]); } while (st.KeepRunningBatch(BatchSize)) { @@ -67,8 +70,7 @@ int main(int argc, char** argv) { 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); + populate(c[i]); } st.ResumeTiming(); } @@ -108,17 +110,21 @@ int main(int argc, char** argv) { constexpr std::size_t BatchSize = 10; using ValueType = typename Container::value_type; Container c[BatchSize]; - ValueType x = Generate::random(); - ValueType y = random_different_from({x}); - 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); + ValueType x = Generate::random(); + ValueType y = random_different_from({x}); + auto populate = [&](Container& cont) { + assert(cont.size() % 4 == 0); + auto out = cont.begin(); + for (std::size_t i = 0; i != cont.size(); i += 4) { + *out++ = x; + *out++ = x; + *out++ = y; + *out++ = y; } }; for (std::size_t i = 0; i != BatchSize; ++i) { c[i] = Container(size); - alternate(c[i].begin(), size); + populate(c[i]); } while (st.KeepRunningBatch(BatchSize)) { @@ -130,7 +136,7 @@ int main(int argc, char** argv) { st.PauseTiming(); for (std::size_t i = 0; i != BatchSize; ++i) { - alternate(c[i].begin(), size); + populate(c[i]); } st.ResumeTiming(); } diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp index 9aa96316d6e33..c5b5439e88e71 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp @@ -91,15 +91,19 @@ int main(int argc, char** argv) { std::size_t const size = st.range(0); using ValueType = typename Container::value_type; Container c(size); - ValueType x = Generate::random(); - ValueType y = random_different_from({x}); - 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); + ValueType x = Generate::random(); + ValueType y = random_different_from({x}); + auto populate = [&](Container& cont) { + assert(cont.size() % 4 == 0); + auto out = cont.begin(); + for (std::size_t i = 0; i != cont.size(); i += 4) { + *out++ = x; + *out++ = x; + *out++ = y; + *out++ = y; } }; - alternate(c.begin(), size); + populate(c); std::vector out(size); From 4b4ebda8b17978d7cca4e7a78ad8b8c3997312cf Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 25 Feb 2025 11:13:37 -0500 Subject: [PATCH 12/15] Address comments on shift_{left,right} benchmarks --- .../algorithms/modifying/shift_left.bench.cpp | 14 +++++++++++--- .../algorithms/modifying/shift_right.bench.cpp | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp index 906e825992b9d..8c3b410bf2ec6 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "benchmark/benchmark.h" @@ -22,7 +23,7 @@ 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(normal container) + // Benchmark std::shift_left where we shift exactly one element, which is the worst case. { auto bm = [](std::string name, auto shift_left) { benchmark::RegisterBenchmark( @@ -32,12 +33,19 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; std::generate_n(std::back_inserter(c), size, [] { return Generate::random(); }); + std::size_t n = 1; - auto const n = 9 * (size / 10); // shift all but 10% of the range + // To avoid ending up with a fully moved-from range, restore the element that gets + // overwritten by the shift after performing the shift. + auto first_element = c.begin(); + auto last_element = std::next(c.begin(), size - 1); for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); - auto result = shift_left(c.begin(), c.end(), n); + benchmark::DoNotOptimize(n); + ValueType tmp = *first_element; + auto result = shift_left(c.begin(), c.end(), n); + *last_element = std::move(tmp); benchmark::DoNotOptimize(result); } }) diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp index ef55e55f3ca10..7e55c390b1951 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "benchmark/benchmark.h" @@ -22,7 +23,7 @@ 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(normal container) + // Benchmark std::shift_right where we shift exactly one element, which is the worst case. { auto bm = [](std::string name, auto shift_right) { benchmark::RegisterBenchmark( @@ -32,12 +33,19 @@ int main(int argc, char** argv) { using ValueType = typename Container::value_type; Container c; std::generate_n(std::back_inserter(c), size, [] { return Generate::random(); }); + std::size_t n = 1; - auto const n = 9 * (size / 10); // shift all but 10% of the range + // To avoid ending up with a fully moved-from range, restore the element that gets + // overwritten by the shift after performing the shift. + auto first_element = c.begin(); + auto last_element = std::next(c.begin(), size - 1); for ([[maybe_unused]] auto _ : st) { benchmark::DoNotOptimize(c); - auto result = shift_right(c.begin(), c.end(), n); + benchmark::DoNotOptimize(n); + ValueType tmp = *last_element; + auto result = shift_right(c.begin(), c.end(), n); + *first_element = std::move(tmp); benchmark::DoNotOptimize(result); } }) From da6d83f4a90906438e8b70065041c57a8b33169e Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 25 Feb 2025 11:17:13 -0500 Subject: [PATCH 13/15] Avoid two decls on a line --- libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp | 3 ++- .../benchmarks/algorithms/modifying/move_backward.bench.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp index 8213c16b78e6b..7473dffc123ce 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp @@ -29,7 +29,8 @@ int main(int argc, char** argv) { benchmark::RegisterBenchmark(name, [move](auto& st) { std::size_t const size = st.range(0); using ValueType = typename Container::value_type; - Container c1(size), c2(size); + Container c1(size); + Container c2(size); std::generate_n(c1.begin(), size, [] { return Generate::random(); }); Container* in = &c1; diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp index a5bfc75ec94e8..1cdc880910686 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp @@ -29,7 +29,8 @@ int main(int argc, char** argv) { benchmark::RegisterBenchmark(name, [move_backward](auto& st) { std::size_t const size = st.range(0); using ValueType = typename Container::value_type; - Container c1(size), c2(size); + Container c1(size); + Container c2(size); std::generate_n(c1.begin(), size, [] { return Generate::random(); }); Container* in = &c1; From fd313e5c044044e209a86ceb7decfa249e4c6e53 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 25 Feb 2025 11:20:22 -0500 Subject: [PATCH 14/15] Add non-powers-of-two --- libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp | 1 + libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp | 1 + libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp | 1 + .../test/benchmarks/algorithms/modifying/generate_n.bench.cpp | 1 + libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp | 2 ++ .../test/benchmarks/algorithms/modifying/remove_copy.bench.cpp | 2 ++ libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp | 2 ++ .../test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp | 1 + .../test/benchmarks/algorithms/modifying/shift_left.bench.cpp | 1 + .../test/benchmarks/algorithms/modifying/shift_right.bench.cpp | 1 + .../test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp | 1 + .../benchmarks/algorithms/modifying/transform.binary.bench.cpp | 1 + .../benchmarks/algorithms/modifying/transform.unary.bench.cpp | 1 + libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp | 2 ++ .../test/benchmarks/algorithms/modifying/unique_copy.bench.cpp | 1 + 15 files changed, 19 insertions(+) diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp index 7b3534969b247..9060752259eb9 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp @@ -42,6 +42,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp index 700d109fdbc61..8ad3e7534b1ef 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp @@ -42,6 +42,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp index e3a8d650b5159..34354e5af0efb 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp @@ -43,6 +43,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp index 3671b66b21a85..9f8fb1e07524d 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp @@ -43,6 +43,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp index f0713dc7f9720..19cd49641e173 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp @@ -75,6 +75,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; @@ -138,6 +139,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp index b0bc58e8a7a2f..582175b8a32cc 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp @@ -62,6 +62,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; @@ -109,6 +110,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp index 5df7aa1fbbc04..bdf26acb8d07f 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp @@ -65,6 +65,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; @@ -111,6 +112,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp index 4f685ba9a8c7e..4ba9110552807 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp @@ -46,6 +46,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp index 8c3b410bf2ec6..b26526484c66a 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp @@ -50,6 +50,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp index 7e55c390b1951..42946760fc8a3 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp @@ -50,6 +50,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp index 541f4ae17cc7a..e9fb201a57d34 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp @@ -46,6 +46,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp index cb6cfceee5bc4..c4ea7535aefef 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp @@ -53,6 +53,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp index db02fb67556b9..9ae40cb488085 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp @@ -48,6 +48,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp index baec1fc8187d9..c0aee942eef64 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp @@ -76,6 +76,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; @@ -142,6 +143,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp index c5b5439e88e71..45b52dd23b695 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp @@ -115,6 +115,7 @@ int main(int argc, char** argv) { } }) ->Arg(32) + ->Arg(50) // non power-of-two ->Arg(1024) ->Arg(8192); }; From 50c0cc8f7df85e31e2fe4c72987c1a170e452151 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 17 Mar 2025 09:44:54 -0400 Subject: [PATCH 15/15] Guard C++23 --- .../test/benchmarks/algorithms/modifying/rotate.bench.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp index 2aa0d6b696e59..d9548a3c176d2 100644 --- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp +++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp @@ -72,9 +72,11 @@ int main(int argc, char** argv) { bm.operator()>("std::rotate(vector) (by 1/3)", std_rotate, 0.33); bm.operator()>("std::rotate(vector) (by 1/2)", std_rotate, 0.50); +#if TEST_STD_VER >= 23 // vector::iterator is not std::permutable before C++23 bm.operator()>("rng::rotate(vector) (by 1/4)", std::ranges::rotate, 0.25); bm.operator()>("rng::rotate(vector) (by 1/3)", std::ranges::rotate, 0.33); bm.operator()>("rng::rotate(vector) (by 1/2)", std::ranges::rotate, 0.50); +#endif } // Benchmark {std,ranges}::rotate where we rotate a single element from the beginning to the end of the range. @@ -108,7 +110,9 @@ int main(int argc, char** argv) { bm.operator()>("rng::rotate(list) (1 element forward)", std::ranges::rotate); bm.operator()>("std::rotate(vector) (1 element forward)", std_rotate); +#if TEST_STD_VER >= 23 // vector::iterator is not std::permutable before C++23 bm.operator()>("rng::rotate(vector) (1 element forward)", std::ranges::rotate); +#endif } // Benchmark {std,ranges}::rotate where we rotate a single element from the end to the beginning of the range. @@ -142,7 +146,9 @@ int main(int argc, char** argv) { bm.operator()>("rng::rotate(list) (1 element backward)", std::ranges::rotate); bm.operator()>("std::rotate(vector) (1 element backward)", std_rotate); +#if TEST_STD_VER >= 23 // vector::iterator is not std::permutable before C++23 bm.operator()>("rng::rotate(vector) (1 element backward)", std::ranges::rotate); +#endif } benchmark::Initialize(&argc, argv);