@@ -38,7 +38,7 @@ int main(int argc, char** argv) {
38
38
});
39
39
};
40
40
41
- // Benchmark {std,ranges}::search where the needle is never found
41
+ // Benchmark {std,ranges}::search where the needle is never found (worst case).
42
42
{
43
43
auto bm = []<class Container >(std::string name, auto search) {
44
44
benchmark::RegisterBenchmark (
@@ -80,7 +80,7 @@ int main(int argc, char** argv) {
80
80
bm.operator ()<std::list<int >>(" rng::search(list<int>, pred) (no match)" , ranges_search_pred);
81
81
}
82
82
83
- // Benchmark {std,ranges}::search where we intersperse "near matches" inside the haystack
83
+ // Benchmark {std,ranges}::search where we intersperse "near matches" inside the haystack.
84
84
{
85
85
auto bm = []<class Container >(std::string name, auto search) {
86
86
benchmark::RegisterBenchmark (
@@ -132,6 +132,87 @@ int main(int argc, char** argv) {
132
132
bm.operator ()<std::list<int >>(" rng::search(list<int>, pred) (near matches)" , ranges_search_pred);
133
133
}
134
134
135
+ // Special case: the two ranges are the same length (and they are equal, which is the worst case).
136
+ {
137
+ auto bm = []<class Container >(std::string name, auto search) {
138
+ benchmark::RegisterBenchmark (
139
+ name,
140
+ [search](auto & st) {
141
+ std::size_t const size = st.range (0 );
142
+ using ValueType = typename Container::value_type;
143
+ ValueType x = Generate<ValueType>::random ();
144
+ Container haystack (size, x);
145
+ Container needle (size, x);
146
+
147
+ for ([[maybe_unused]] auto _ : st) {
148
+ benchmark::DoNotOptimize (haystack);
149
+ benchmark::DoNotOptimize (needle);
150
+ auto result = search (haystack.begin (), haystack.end (), needle.begin (), needle.end ());
151
+ benchmark::DoNotOptimize (result);
152
+ }
153
+ })
154
+ ->Arg (1000 ) // non power-of-two
155
+ ->Arg (1024 )
156
+ ->Arg (8192 );
157
+ };
158
+ // {std,ranges}::search
159
+ bm.operator ()<std::vector<int >>(" std::search(vector<int>) (same length)" , std_search);
160
+ bm.operator ()<std::deque<int >>(" std::search(deque<int>) (same length)" , std_search);
161
+ bm.operator ()<std::list<int >>(" std::search(list<int>) (same length)" , std_search);
162
+ bm.operator ()<std::vector<int >>(" rng::search(vector<int>) (same length)" , std::ranges::search);
163
+ bm.operator ()<std::deque<int >>(" rng::search(deque<int>) (same length)" , std::ranges::search);
164
+ bm.operator ()<std::list<int >>(" rng::search(list<int>) (same length)" , std::ranges::search);
165
+
166
+ // {std,ranges}::search(pred)
167
+ bm.operator ()<std::vector<int >>(" std::search(vector<int>, pred) (same length)" , std_search_pred);
168
+ bm.operator ()<std::deque<int >>(" std::search(deque<int>, pred) (same length)" , std_search_pred);
169
+ bm.operator ()<std::list<int >>(" std::search(list<int>, pred) (same length)" , std_search_pred);
170
+ bm.operator ()<std::vector<int >>(" rng::search(vector<int>, pred) (same length)" , ranges_search_pred);
171
+ bm.operator ()<std::deque<int >>(" rng::search(deque<int>, pred) (same length)" , ranges_search_pred);
172
+ bm.operator ()<std::list<int >>(" rng::search(list<int>, pred) (same length)" , ranges_search_pred);
173
+ }
174
+
175
+ // Special case: the needle contains a single element (which we never find, i.e. the worst case).
176
+ {
177
+ auto bm = []<class Container >(std::string name, auto search) {
178
+ benchmark::RegisterBenchmark (
179
+ name,
180
+ [search](auto & st) {
181
+ std::size_t const size = st.range (0 );
182
+ using ValueType = typename Container::value_type;
183
+ ValueType x = Generate<ValueType>::random ();
184
+ ValueType y = random_different_from ({x});
185
+ Container haystack (size, x);
186
+ Container needle (1 , y);
187
+
188
+ for ([[maybe_unused]] auto _ : st) {
189
+ benchmark::DoNotOptimize (haystack);
190
+ benchmark::DoNotOptimize (needle);
191
+ auto result = search (haystack.begin (), haystack.end (), needle.begin (), needle.end ());
192
+ benchmark::DoNotOptimize (result);
193
+ }
194
+ })
195
+ ->Arg (1000 ) // non power-of-two
196
+ ->Arg (1024 )
197
+ ->Arg (8192 );
198
+ };
199
+ // {std,ranges}::search
200
+ bm.operator ()<std::vector<int >>(" std::search(vector<int>) (single element)" , std_search);
201
+ bm.operator ()<std::deque<int >>(" std::search(deque<int>) (single element)" , std_search);
202
+ bm.operator ()<std::list<int >>(" std::search(list<int>) (single element)" , std_search);
203
+ bm.operator ()<std::vector<int >>(" rng::search(vector<int>) (single element)" , std::ranges::search);
204
+ bm.operator ()<std::deque<int >>(" rng::search(deque<int>) (single element)" , std::ranges::search);
205
+ bm.operator ()<std::list<int >>(" rng::search(list<int>) (single element)" , std::ranges::search);
206
+
207
+ // {std,ranges}::search(pred)
208
+ bm.operator ()<std::vector<int >>(" std::search(vector<int>, pred) (single element)" , std_search_pred);
209
+ bm.operator ()<std::deque<int >>(" std::search(deque<int>, pred) (single element)" , std_search_pred);
210
+ bm.operator ()<std::list<int >>(" std::search(list<int>, pred) (single element)" , std_search_pred);
211
+ bm.operator ()<std::vector<int >>(" rng::search(vector<int>, pred) (single element)" , ranges_search_pred);
212
+ bm.operator ()<std::deque<int >>(" rng::search(deque<int>, pred) (single element)" , ranges_search_pred);
213
+ bm.operator ()<std::list<int >>(" rng::search(list<int>, pred) (single element)" , ranges_search_pred);
214
+ }
215
+
135
216
benchmark::Initialize (&argc, argv);
136
217
benchmark::RunSpecifiedBenchmarks ();
137
218
benchmark::Shutdown ();
0 commit comments