diff --git a/libcxx/test/benchmarks/algorithms/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/copy.bench.cpp deleted file mode 100644 index b6f0f15eb7703..0000000000000 --- a/libcxx/test/benchmarks/algorithms/copy.bench.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 - -#include -#include -#include - -static void bm_ranges_copy_vb(benchmark::State& state, bool aligned) { - auto n = state.range(); - std::vector in(n, true); - std::vector out(aligned ? n : n + 8); - benchmark::DoNotOptimize(&in); - auto dst = aligned ? out.begin() : out.begin() + 4; - for (auto _ : state) { - benchmark::DoNotOptimize(std::ranges::copy(in, dst)); - benchmark::DoNotOptimize(&out); - } -} - -static void bm_ranges_copy_n_vb(benchmark::State& state, bool aligned) { - auto n = state.range(); - std::vector in(n, true); - std::vector out(aligned ? n : n + 8); - benchmark::DoNotOptimize(&in); - auto src = in.begin(); - auto dst = aligned ? out.begin() : out.begin() + 4; - for (auto _ : state) { - benchmark::DoNotOptimize(std::ranges::copy_n(src, n, dst)); - benchmark::DoNotOptimize(&out); - } -} - -static void bm_copy_vb(benchmark::State& state, bool aligned) { - auto n = state.range(); - std::vector in(n, true); - std::vector out(aligned ? n : n + 8); - benchmark::DoNotOptimize(&in); - auto beg = in.begin(); - auto end = in.end(); - auto dst = aligned ? out.begin() : out.begin() + 4; - for (auto _ : state) { - benchmark::DoNotOptimize(std::copy(beg, end, dst)); - benchmark::DoNotOptimize(&out); - } -} - -static void bm_copy_n_vb(benchmark::State& state, bool aligned) { - auto n = state.range(); - std::vector in(n, true); - std::vector out(aligned ? n : n + 8); - benchmark::DoNotOptimize(&in); - auto src = in.begin(); - auto dst = aligned ? out.begin() : out.begin() + 4; - for (auto _ : state) { - benchmark::DoNotOptimize(std::copy_n(src, n, dst)); - benchmark::DoNotOptimize(&out); - } -} - -static void bm_ranges_copy_vb_aligned(benchmark::State& state) { bm_ranges_copy_vb(state, true); } -static void bm_ranges_copy_vb_unaligned(benchmark::State& state) { bm_ranges_copy_vb(state, false); } -static void bm_ranges_copy_n_vb_aligned(benchmark::State& state) { bm_ranges_copy_n_vb(state, true); } -static void bm_ranges_copy_n_vb_unaligned(benchmark::State& state) { bm_ranges_copy_n_vb(state, false); } - -static void bm_copy_vb_aligned(benchmark::State& state) { bm_copy_vb(state, true); } -static void bm_copy_vb_unaligned(benchmark::State& state) { bm_copy_vb(state, false); } -static void bm_copy_n_vb_aligned(benchmark::State& state) { bm_copy_n_vb(state, true); } -static void bm_copy_n_vb_unaligned(benchmark::State& state) { bm_copy_n_vb(state, false); } - -// Test std::ranges::copy for vector::iterator -BENCHMARK(bm_ranges_copy_vb_aligned)->Range(8, 1 << 16)->DenseRange(102400, 204800, 4096); -BENCHMARK(bm_ranges_copy_n_vb_aligned)->Range(8, 1 << 20); -BENCHMARK(bm_ranges_copy_vb_unaligned)->Range(8, 1 << 20); -BENCHMARK(bm_ranges_copy_n_vb_unaligned)->Range(8, 1 << 20); - -// Test std::copy for vector::iterator -BENCHMARK(bm_copy_vb_aligned)->Range(8, 1 << 20); -BENCHMARK(bm_copy_n_vb_aligned)->Range(8, 1 << 20); -BENCHMARK(bm_copy_vb_unaligned)->Range(8, 1 << 20); -BENCHMARK(bm_copy_n_vb_unaligned)->Range(8, 1 << 20); - -BENCHMARK_MAIN(); diff --git a/libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp deleted file mode 100644 index c943d9a874b49..0000000000000 --- a/libcxx/test/benchmarks/algorithms/copy_backward.bench.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 - -#include -#include -#include - -static void bm_ranges_copy_backward_vb(benchmark::State& state, bool aligned) { - auto n = state.range(); - std::vector in(n, true); - std::vector out(aligned ? n : n + 8); - benchmark::DoNotOptimize(&in); - auto dst = aligned ? out.end() : out.end() - 4; - for (auto _ : state) { - benchmark::DoNotOptimize(std::ranges::copy_backward(in, dst)); - benchmark::DoNotOptimize(&out); - } -} - -static void bm_copy_backward_vb(benchmark::State& state, bool aligned) { - auto n = state.range(); - std::vector in(n, true); - std::vector out(aligned ? n : n + 8); - benchmark::DoNotOptimize(&in); - auto beg = in.begin(); - auto end = in.end(); - auto dst = aligned ? out.end() : out.end() - 4; - for (auto _ : state) { - benchmark::DoNotOptimize(std::copy_backward(beg, end, dst)); - benchmark::DoNotOptimize(&out); - } -} - -static void bm_ranges_copy_backward_vb_aligned(benchmark::State& state) { bm_ranges_copy_backward_vb(state, true); } -static void bm_ranges_copy_backward_vb_unaligned(benchmark::State& state) { bm_ranges_copy_backward_vb(state, false); } - -static void bm_copy_backward_vb_aligned(benchmark::State& state) { bm_copy_backward_vb(state, true); } -static void bm_copy_backward_vb_unaligned(benchmark::State& state) { bm_copy_backward_vb(state, false); } - -// Test std::ranges::copy_backward for vector::iterator -BENCHMARK(bm_ranges_copy_backward_vb_aligned)->Range(8, 1 << 16)->DenseRange(102400, 204800, 4096); -BENCHMARK(bm_ranges_copy_backward_vb_unaligned)->Range(8, 1 << 20); - -// Test std::copy_backward for vector::iterator -BENCHMARK(bm_copy_backward_vb_aligned)->Range(8, 1 << 20); -BENCHMARK(bm_copy_backward_vb_unaligned)->Range(8, 1 << 20); - -BENCHMARK_MAIN(); diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp new file mode 100644 index 0000000000000..3549d918478bd --- /dev/null +++ b/libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include +#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_copy = [](auto first, auto last, auto out) { return std::copy(first, last, out); }; + + // {std,ranges}::copy(normal container) + { + auto bm = [](std::string name, auto copy) { + benchmark::RegisterBenchmark(name, [copy](auto& st) { + std::size_t const n = st.range(0); + using ValueType = typename Container::value_type; + Container c; + std::generate_n(std::back_inserter(c), n, [] { return Generate::random(); }); + + std::vector out(n); + + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + benchmark::DoNotOptimize(out); + auto result = copy(c.begin(), c.end(), out.begin()); + benchmark::DoNotOptimize(result); + } + })->Range(8, 1 << 20); + }; + bm.operator()>("std::copy(vector)", std_copy); + bm.operator()>("std::copy(deque)", std_copy); + bm.operator()>("std::copy(list)", std_copy); + bm.operator()>("rng::copy(vector)", std::ranges::copy); + bm.operator()>("rng::copy(deque)", std::ranges::copy); + bm.operator()>("rng::copy(list)", std::ranges::copy); + } + + // {std,ranges}::copy(vector) + { + auto bm = [](std::string name, auto copy) { + benchmark::RegisterBenchmark(name, [copy](auto& st) { + std::size_t const n = st.range(0); + std::vector in(n, true); + std::vector out(Aligned ? n : n + 8); + auto first = in.begin(); + auto last = in.end(); + auto dst = Aligned ? out.begin() : out.begin() + 4; + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(in); + benchmark::DoNotOptimize(out); + auto result = copy(first, last, dst); + benchmark::DoNotOptimize(result); + } + })->Range(64, 1 << 20); + }; + bm.operator()("std::copy(vector) (aligned)", std_copy); + bm.operator()("std::copy(vector) (unaligned)", std_copy); +#if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 + bm.operator()("rng::copy(vector) (aligned)", std::ranges::copy); + bm.operator()("rng::copy(vector) (unaligned)", std::ranges::copy); +#endif + } + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); + return 0; +} diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp new file mode 100644 index 0000000000000..f97a7a84d5e0a --- /dev/null +++ b/libcxx/test/benchmarks/algorithms/modifying/copy_backward.bench.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include +#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_copy_backward = [](auto first, auto last, auto out) { return std::copy_backward(first, last, out); }; + + // {std,ranges}::copy_n(normal container) + { + auto bm = [](std::string name, auto copy_backward) { + benchmark::RegisterBenchmark(name, [copy_backward](auto& st) { + std::size_t const n = st.range(0); + using ValueType = typename Container::value_type; + Container c; + std::generate_n(std::back_inserter(c), n, [] { return Generate::random(); }); + + std::vector out(n); + + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + benchmark::DoNotOptimize(out); + auto result = copy_backward(c.begin(), c.end(), out.end()); + benchmark::DoNotOptimize(result); + } + })->Range(8, 1 << 20); + }; + bm.operator()>("std::copy_backward(vector)", std_copy_backward); + bm.operator()>("std::copy_backward(deque)", std_copy_backward); + bm.operator()>("std::copy_backward(list)", std_copy_backward); + bm.operator()>("rng::copy_backward(vector)", std::ranges::copy_backward); + bm.operator()>("rng::copy_backward(deque)", std::ranges::copy_backward); + bm.operator()>("rng::copy_backward(list)", std::ranges::copy_backward); + } + + // {std,ranges}::copy_n(vector) + { + auto bm = [](std::string name, auto copy_backward) { + benchmark::RegisterBenchmark(name, [copy_backward](auto& st) { + std::size_t const n = st.range(0); + std::vector in(n, true); + std::vector out(Aligned ? n : n + 8); + benchmark::DoNotOptimize(&in); + auto first = in.begin(); + auto last = in.end(); + auto dst = Aligned ? out.end() : out.end() - 4; + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(in); + benchmark::DoNotOptimize(out); + auto result = copy_backward(first, last, dst); + benchmark::DoNotOptimize(result); + } + })->Range(64, 1 << 20); + }; + bm.operator()("std::copy_backward(vector) (aligned)", std_copy_backward); + bm.operator()("std::copy_backward(vector) (unaligned)", std_copy_backward); +#if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 + bm.operator()("rng::copy_backward(vector) (aligned)", std::ranges::copy_backward); + bm.operator()("rng::copy_backward(vector) (unaligned)", std::ranges::copy_backward); +#endif + } + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); + return 0; +} diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp new file mode 100644 index 0000000000000..76c653fc7f941 --- /dev/null +++ b/libcxx/test/benchmarks/algorithms/modifying/copy_if.bench.cpp @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "../../GenerateInput.h" + +int main(int argc, char** argv) { + auto std_copy_if = [](auto first, auto last, auto out, auto pred) { return std::copy_if(first, last, out, pred); }; + + // Benchmark {std,ranges}::copy_if where we copy one out of two element, in alternance. + // This is basically the worst case for this algorithm, I don't think there are many + // optimizations that can be applied in this case. + { + auto bm = [](std::string name, auto copy_if) { + benchmark::RegisterBenchmark(name, [copy_if](auto& st) { + std::size_t const n = st.range(0); + using ValueType = typename Container::value_type; + Container c; + std::generate_n(std::back_inserter(c), n, [] { return Generate::random(); }); + + std::vector out(n); + + for ([[maybe_unused]] auto _ : st) { + bool do_copy = false; + auto pred = [&do_copy](auto& element) { + benchmark::DoNotOptimize(element); + do_copy = !do_copy; + return do_copy; + }; + benchmark::DoNotOptimize(c); + benchmark::DoNotOptimize(out); + auto result = copy_if(c.begin(), c.end(), out.begin(), pred); + benchmark::DoNotOptimize(result); + } + })->Range(8, 1 << 20); + }; + bm.operator()>("std::copy_if(vector) (every other)", std_copy_if); + bm.operator()>("std::copy_if(deque) (every other)", std_copy_if); + bm.operator()>("std::copy_if(list) (every other)", std_copy_if); + + bm.operator()>("rng::copy_if(vector) (every other)", std::ranges::copy_if); + bm.operator()>("rng::copy_if(deque) (every other)", std::ranges::copy_if); + bm.operator()>("rng::copy_if(list) (every other)", std::ranges::copy_if); + } + + // Benchmark {std,ranges}::copy_if where we copy the full range. + // Copy the full range. + { + auto bm = [](std::string name, auto copy_if) { + benchmark::RegisterBenchmark(name, [copy_if](auto& st) { + std::size_t const n = st.range(0); + using ValueType = typename Container::value_type; + Container c; + std::generate_n(std::back_inserter(c), n, [] { return Generate::random(); }); + + std::vector out(n); + + for ([[maybe_unused]] auto _ : st) { + auto pred = [](auto& element) { + benchmark::DoNotOptimize(element); + return true; + }; + benchmark::DoNotOptimize(c); + benchmark::DoNotOptimize(out); + auto result = copy_if(c.begin(), c.end(), out.begin(), pred); + benchmark::DoNotOptimize(result); + } + })->Range(8, 1 << 20); + }; + bm.operator()>("std::copy_if(vector) (entire range)", std_copy_if); + bm.operator()>("std::copy_if(deque) (entire range)", std_copy_if); + bm.operator()>("std::copy_if(list) (entire range)", std_copy_if); + + bm.operator()>("rng::copy_if(vector) (entire range)", std::ranges::copy_if); + bm.operator()>("rng::copy_if(deque) (entire range)", std::ranges::copy_if); + bm.operator()>("rng::copy_if(list) (entire range)", std::ranges::copy_if); + } + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); + return 0; +} diff --git a/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp new file mode 100644 index 0000000000000..35d3c5c78df13 --- /dev/null +++ b/libcxx/test/benchmarks/algorithms/modifying/copy_n.bench.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include +#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_copy_n = [](auto first, auto n, auto out) { return std::copy_n(first, n, out); }; + + // {std,ranges}::copy_n(normal container) + { + auto bm = [](std::string name, auto copy_n) { + benchmark::RegisterBenchmark(name, [copy_n](auto& st) { + std::size_t const n = st.range(0); + using ValueType = typename Container::value_type; + Container c; + std::generate_n(std::back_inserter(c), n, [] { return Generate::random(); }); + + std::vector out(n); + + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + benchmark::DoNotOptimize(out); + auto result = copy_n(c.begin(), n, out.begin()); + benchmark::DoNotOptimize(result); + } + })->Range(8, 1 << 20); + }; + bm.operator()>("std::copy_n(vector)", std_copy_n); + bm.operator()>("std::copy_n(deque)", std_copy_n); + bm.operator()>("std::copy_n(list)", std_copy_n); + bm.operator()>("rng::copy_n(vector)", std::ranges::copy_n); + bm.operator()>("rng::copy_n(deque)", std::ranges::copy_n); + bm.operator()>("rng::copy_n(list)", std::ranges::copy_n); + } + + // {std,ranges}::copy_n(vector) + { + auto bm = [](std::string name, auto copy_n) { + benchmark::RegisterBenchmark(name, [copy_n](auto& st) { + std::size_t const n = st.range(0); + std::vector in(n, true); + std::vector out(Aligned ? n : n + 8); + auto first = in.begin(); + auto dst = Aligned ? out.begin() : out.begin() + 4; + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(in); + benchmark::DoNotOptimize(out); + auto result = copy_n(first, n, dst); + benchmark::DoNotOptimize(result); + } + })->Range(64, 1 << 20); + }; + bm.operator()("std::copy_n(vector) (aligned)", std_copy_n); + bm.operator()("std::copy_n(vector) (unaligned)", std_copy_n); +#if TEST_STD_VER >= 23 // vector::iterator is not an output_iterator before C++23 + bm.operator()("rng::copy_n(vector) (aligned)", std::ranges::copy_n); + bm.operator()("rng::copy_n(vector) (unaligned)", std::ranges::copy_n); +#endif + } + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); + return 0; +}