1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10
11#include <algorithm>
12#include <cassert>
13#include <cstddef>
14#include <deque>
15#include <forward_list>
16#include <list>
17#include <string>
18#include <vector>
19
20#include <benchmark/benchmark.h>
21#include "../../GenerateInput.h"
22
23int main(int argc, char** argv) {
24 auto ranges_ends_with_pred = [](auto first1, auto last1, auto first2, auto last2) {
25 return std::ranges::ends_with(first1, last1, first2, last2, [](auto x, auto y) {
26 benchmark::DoNotOptimize(x);
27 benchmark::DoNotOptimize(y);
28 return x == y;
29 });
30 };
31
32 // Benchmark ranges::ends_with where we find the mismatching element at the very end.
33 {
34 auto bm = []<class Container>(std::string name, auto ends_with) {
35 benchmark::RegisterBenchmark(
36 name,
37 [ends_with](auto& st) {
38 std::size_t const size = st.range(0);
39 using ValueType = typename Container::value_type;
40 ValueType x = Generate<ValueType>::random();
41 ValueType y = random_different_from({x});
42 Container c1(size, x);
43 Container c2(size, x);
44 assert(size != 0);
45 *std::next(c2.begin(), size - 1) = y; // set last element to y
46
47 for ([[maybe_unused]] auto _ : st) {
48 benchmark::DoNotOptimize(c1);
49 benchmark::DoNotOptimize(c2);
50 auto result = ends_with(c1.begin(), c1.end(), c2.begin(), c2.end());
51 benchmark::DoNotOptimize(result);
52 }
53 })
54 ->Arg(8)
55 ->Arg(50) // non power-of-two
56 ->Arg(1024)
57 ->Arg(8192)
58 ->Arg(1 << 20);
59 };
60 bm.operator()<std::vector<int>>("rng::ends_with(vector<int>) (mismatch at end)", std::ranges::ends_with);
61 bm.operator()<std::deque<int>>("rng::ends_with(deque<int>) (mismatch at end)", std::ranges::ends_with);
62 bm.operator()<std::list<int>>("rng::ends_with(list<int>) (mismatch at end)", std::ranges::ends_with);
63 bm.operator()<std::forward_list<int>>(
64 "rng::ends_with(forward_list<int>) (mismatch at end)", std::ranges::ends_with);
65
66 bm.operator()<std::vector<int>>(name: "rng::ends_with(vector<int>, pred) (mismatch at end)", ends_with: ranges_ends_with_pred);
67 bm.operator()<std::deque<int>>(name: "rng::ends_with(deque<int>, pred) (mismatch at end)", ends_with: ranges_ends_with_pred);
68 bm.operator()<std::list<int>>(name: "rng::ends_with(list<int>, pred) (mismatch at end)", ends_with: ranges_ends_with_pred);
69 bm.operator()<std::forward_list<int>>(
70 name: "rng::ends_with(forward_list<int>, pred) (mismatch at end)", ends_with: ranges_ends_with_pred);
71 }
72
73 // Benchmark ranges::ends_with where we find the mismatching element at the very beginning.
74 {
75 auto bm = []<class Container>(std::string name, auto ends_with) {
76 benchmark::RegisterBenchmark(
77 name,
78 [ends_with](auto& st) {
79 std::size_t const size = st.range(0);
80 using ValueType = typename Container::value_type;
81 ValueType x = Generate<ValueType>::random();
82 ValueType y = random_different_from({x});
83 Container c1(size, x);
84 Container c2(size, x);
85 assert(size != 0);
86 c2.front() = y;
87
88 for ([[maybe_unused]] auto _ : st) {
89 benchmark::DoNotOptimize(c1);
90 benchmark::DoNotOptimize(c2);
91 auto result = ends_with(c1.begin(), c1.end(), c2.begin(), c2.end());
92 benchmark::DoNotOptimize(result);
93 }
94 })
95 ->Arg(8)
96 ->Arg(50) // non power-of-two
97 ->Arg(1024)
98 ->Arg(8192)
99 ->Arg(1 << 20);
100 };
101 bm.operator()<std::vector<int>>("rng::ends_with(vector<int>) (mismatch at start)", std::ranges::ends_with);
102 bm.operator()<std::deque<int>>("rng::ends_with(deque<int>) (mismatch at start)", std::ranges::ends_with);
103 bm.operator()<std::list<int>>("rng::ends_with(list<int>) (mismatch at start)", std::ranges::ends_with);
104 bm.operator()<std::forward_list<int>>(
105 "rng::ends_with(forward_list<int>) (mismatch at start)", std::ranges::ends_with);
106
107 bm.operator()<std::vector<int>>(name: "rng::ends_with(vector<int>, pred) (mismatch at start)", ends_with: ranges_ends_with_pred);
108 bm.operator()<std::deque<int>>(name: "rng::ends_with(deque<int>, pred) (mismatch at start)", ends_with: ranges_ends_with_pred);
109 bm.operator()<std::list<int>>(name: "rng::ends_with(list<int>, pred) (mismatch at start)", ends_with: ranges_ends_with_pred);
110 bm.operator()<std::forward_list<int>>(
111 name: "rng::ends_with(forward_list<int>, pred) (mismatch at start)", ends_with: ranges_ends_with_pred);
112 }
113
114 benchmark::Initialize(&argc, argv);
115 benchmark::RunSpecifiedBenchmarks();
116 benchmark::Shutdown();
117 return 0;
118}
119

source code of libcxx/test/benchmarks/algorithms/nonmodifying/ends_with.bench.cpp