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 |
10 | |
11 | #include <algorithm> |
12 | #include <deque> |
13 | |
14 | #include "benchmark/benchmark.h" |
15 | |
16 | namespace { |
17 | void run_sizes(auto benchmark) { |
18 | benchmark->Arg(0) |
19 | ->Arg(1) |
20 | ->Arg(2) |
21 | ->Arg(64) |
22 | ->Arg(512) |
23 | ->Arg(1024) |
24 | ->Arg(4000) |
25 | ->Arg(4096) |
26 | ->Arg(5500) |
27 | ->Arg(64000) |
28 | ->Arg(65536) |
29 | ->Arg(70000); |
30 | } |
31 | |
32 | template <class FromContainer, class ToContainer, class Func> |
33 | void benchmark_containers(benchmark::State& state, FromContainer& d, ToContainer& v, Func&& func) { |
34 | for (auto _ : state) { |
35 | benchmark::DoNotOptimize(v); |
36 | benchmark::DoNotOptimize(d); |
37 | func(d.begin(), d.end(), v.begin()); |
38 | } |
39 | } |
40 | |
41 | template <class Func> |
42 | void benchmark_deque_vector(benchmark::State& state, Func&& func) { |
43 | auto size = state.range(pos: 0); |
44 | std::deque<int> d; |
45 | d.resize(new_size: size); |
46 | std::ranges::fill(d, 10); |
47 | std::vector<int> v; |
48 | v.resize(new_size: size); |
49 | benchmark_containers(state, d, v, func); |
50 | } |
51 | |
52 | template <class Func> |
53 | void benchmark_deque_deque(benchmark::State& state, Func&& func) { |
54 | auto size = state.range(pos: 0); |
55 | std::deque<int> d; |
56 | d.resize(new_size: size); |
57 | std::ranges::fill(d, 10); |
58 | std::deque<int> v; |
59 | v.resize(new_size: size); |
60 | benchmark_containers(state, d, v, func); |
61 | } |
62 | |
63 | template <class Func> |
64 | void benchmark_vector_deque(benchmark::State& state, Func&& func) { |
65 | auto size = state.range(pos: 0); |
66 | std::vector<int> d; |
67 | d.resize(new_size: size); |
68 | std::ranges::fill(d, 10); |
69 | std::deque<int> v; |
70 | v.resize(new_size: size); |
71 | benchmark_containers(state, d, v, func); |
72 | } |
73 | |
74 | template <class FromContainer, class ToContainer, class Func> |
75 | void benchmark_containers_backward(benchmark::State& state, FromContainer& d, ToContainer& v, Func&& func) { |
76 | for (auto _ : state) { |
77 | benchmark::DoNotOptimize(v); |
78 | benchmark::DoNotOptimize(d); |
79 | func(d.begin(), d.end(), v.end()); |
80 | } |
81 | } |
82 | |
83 | template <class Func> |
84 | void benchmark_deque_vector_backward(benchmark::State& state, Func&& func) { |
85 | auto size = state.range(pos: 0); |
86 | std::deque<int> d; |
87 | d.resize(new_size: size); |
88 | std::ranges::fill(d, 10); |
89 | std::vector<int> v; |
90 | v.resize(new_size: size); |
91 | benchmark_containers_backward(state, d, v, func); |
92 | } |
93 | |
94 | template <class Func> |
95 | void benchmark_deque_deque_backward(benchmark::State& state, Func&& func) { |
96 | auto size = state.range(pos: 0); |
97 | std::deque<int> d; |
98 | d.resize(new_size: size); |
99 | std::ranges::fill(d, 10); |
100 | std::deque<int> v; |
101 | v.resize(new_size: size); |
102 | benchmark_containers_backward(state, d, v, func); |
103 | } |
104 | |
105 | template <class Func> |
106 | void benchmark_vector_deque_backward(benchmark::State& state, Func&& func) { |
107 | auto size = state.range(pos: 0); |
108 | std::vector<int> d; |
109 | d.resize(new_size: size); |
110 | std::ranges::fill(d, 10); |
111 | std::deque<int> v; |
112 | v.resize(new_size: size); |
113 | benchmark_containers_backward(state, d, v, func); |
114 | } |
115 | |
116 | struct CopyFunctor { |
117 | template <class... Args> |
118 | auto operator()(Args... args) const { |
119 | std::copy(std::forward<Args>(args)...); |
120 | } |
121 | } copy; |
122 | |
123 | struct MoveFunctor { |
124 | template <class... Args> |
125 | auto operator()(Args... args) const { |
126 | std::move(std::forward<Args>(args)...); |
127 | } |
128 | } move; |
129 | |
130 | struct CopyBackwardFunctor { |
131 | template <class... Args> |
132 | auto operator()(Args... args) const { |
133 | std::copy_backward(std::forward<Args>(args)...); |
134 | } |
135 | } copy_backward; |
136 | |
137 | struct MoveBackwardFunctor { |
138 | template <class... Args> |
139 | auto operator()(Args... args) const { |
140 | std::move_backward(std::forward<Args>(args)...); |
141 | } |
142 | } move_backward; |
143 | |
144 | // copy |
145 | void BM_deque_vector_copy(benchmark::State& state) { benchmark_deque_vector(state, func&: copy); } |
146 | BENCHMARK(BM_deque_vector_copy)->Apply(func: run_sizes); |
147 | |
148 | void BM_deque_vector_ranges_copy(benchmark::State& state) { benchmark_deque_vector(state, std::ranges::copy); } |
149 | BENCHMARK(BM_deque_vector_ranges_copy)->Apply(func: run_sizes); |
150 | |
151 | void BM_deque_deque_copy(benchmark::State& state) { benchmark_deque_deque(state, func&: copy); } |
152 | BENCHMARK(BM_deque_deque_copy)->Apply(func: run_sizes); |
153 | |
154 | void BM_deque_deque_ranges_copy(benchmark::State& state) { benchmark_deque_deque(state, std::ranges::copy); } |
155 | BENCHMARK(BM_deque_deque_ranges_copy)->Apply(func: run_sizes); |
156 | |
157 | void BM_vector_deque_copy(benchmark::State& state) { benchmark_vector_deque(state, func&: copy); } |
158 | BENCHMARK(BM_vector_deque_copy)->Apply(func: run_sizes); |
159 | |
160 | void BM_vector_deque_ranges_copy(benchmark::State& state) { benchmark_vector_deque(state, std::ranges::copy); } |
161 | BENCHMARK(BM_vector_deque_ranges_copy)->Apply(func: run_sizes); |
162 | |
163 | // move |
164 | void BM_deque_vector_move(benchmark::State& state) { benchmark_deque_vector(state, func&: move); } |
165 | BENCHMARK(BM_deque_vector_move)->Apply(func: run_sizes); |
166 | |
167 | void BM_deque_vector_ranges_move(benchmark::State& state) { benchmark_deque_vector(state, std::ranges::move); } |
168 | BENCHMARK(BM_deque_vector_ranges_move)->Apply(func: run_sizes); |
169 | |
170 | void BM_deque_deque_move(benchmark::State& state) { benchmark_deque_deque(state, func&: move); } |
171 | BENCHMARK(BM_deque_deque_move)->Apply(func: run_sizes); |
172 | |
173 | void BM_deque_deque_ranges_move(benchmark::State& state) { benchmark_deque_deque(state, std::ranges::move); } |
174 | BENCHMARK(BM_deque_deque_ranges_move)->Apply(func: run_sizes); |
175 | |
176 | void BM_vector_deque_move(benchmark::State& state) { benchmark_vector_deque(state, func&: move); } |
177 | BENCHMARK(BM_vector_deque_move)->Apply(func: run_sizes); |
178 | |
179 | void BM_vector_deque_ranges_move(benchmark::State& state) { benchmark_vector_deque(state, std::ranges::move); } |
180 | BENCHMARK(BM_vector_deque_ranges_move)->Apply(func: run_sizes); |
181 | |
182 | // copy_backward |
183 | void BM_deque_vector_copy_backward(benchmark::State& state) { benchmark_deque_vector_backward(state, func&: copy_backward); } |
184 | BENCHMARK(BM_deque_vector_copy_backward)->Apply(func: run_sizes); |
185 | |
186 | void BM_deque_vector_ranges_copy_backward(benchmark::State& state) { |
187 | benchmark_deque_vector_backward(state, std::ranges::copy_backward); |
188 | } |
189 | BENCHMARK(BM_deque_vector_ranges_copy_backward)->Apply(func: run_sizes); |
190 | |
191 | void BM_deque_deque_copy_backward(benchmark::State& state) { benchmark_deque_deque_backward(state, func&: copy_backward); } |
192 | BENCHMARK(BM_deque_deque_copy_backward)->Apply(func: run_sizes); |
193 | |
194 | void BM_deque_deque_ranges_copy_backward(benchmark::State& state) { |
195 | benchmark_deque_deque_backward(state, std::ranges::copy_backward); |
196 | } |
197 | BENCHMARK(BM_deque_deque_ranges_copy_backward)->Apply(func: run_sizes); |
198 | |
199 | void BM_vector_deque_copy_backward(benchmark::State& state) { benchmark_vector_deque_backward(state, func&: copy_backward); } |
200 | BENCHMARK(BM_vector_deque_copy_backward)->Apply(func: run_sizes); |
201 | |
202 | void BM_vector_deque_ranges_copy_backward(benchmark::State& state) { |
203 | benchmark_vector_deque_backward(state, std::ranges::copy_backward); |
204 | } |
205 | BENCHMARK(BM_vector_deque_ranges_copy_backward)->Apply(func: run_sizes); |
206 | |
207 | // move_backward |
208 | void BM_deque_vector_move_backward(benchmark::State& state) { benchmark_deque_vector_backward(state, func&: move_backward); } |
209 | BENCHMARK(BM_deque_vector_move_backward)->Apply(func: run_sizes); |
210 | |
211 | void BM_deque_vector_ranges_move_backward(benchmark::State& state) { |
212 | benchmark_deque_vector_backward(state, std::ranges::move_backward); |
213 | } |
214 | BENCHMARK(BM_deque_vector_ranges_move_backward)->Apply(func: run_sizes); |
215 | |
216 | void BM_deque_deque_move_backward(benchmark::State& state) { benchmark_deque_deque_backward(state, func&: move_backward); } |
217 | BENCHMARK(BM_deque_deque_move_backward)->Apply(func: run_sizes); |
218 | |
219 | void BM_deque_deque_ranges_move_backward(benchmark::State& state) { |
220 | benchmark_deque_deque_backward(state, std::ranges::move_backward); |
221 | } |
222 | BENCHMARK(BM_deque_deque_ranges_move_backward)->Apply(func: run_sizes); |
223 | |
224 | void BM_vector_deque_move_backward(benchmark::State& state) { benchmark_vector_deque_backward(state, func&: move_backward); } |
225 | BENCHMARK(BM_vector_deque_move_backward)->Apply(func: run_sizes); |
226 | |
227 | void BM_vector_deque_ranges_move_backward(benchmark::State& state) { |
228 | benchmark_vector_deque_backward(state, std::ranges::move_backward); |
229 | } |
230 | BENCHMARK(BM_vector_deque_ranges_move_backward)->Apply(func: run_sizes); |
231 | |
232 | } // namespace |
233 | |
234 | BENCHMARK_MAIN(); |
235 | |