12
12
#include < vector>
13
13
using namespace std ::string_view_literals;
14
14
15
- const char src_haystack[] =
15
+ constexpr std::string_view common_src_data =
16
16
" Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mollis imperdiet massa, at dapibus elit interdum "
17
17
" ac. In eget sollicitudin mi. Nam at tellus at sapien tincidunt sollicitudin vel non eros. Pellentesque nunc nunc, "
18
18
" ullamcorper eu accumsan at, pulvinar non turpis. Quisque vel mauris pulvinar, pretium purus vel, ultricies erat. "
@@ -43,13 +43,42 @@ const char src_haystack[] =
43
43
" euismod eros, ut posuere ligula ullamcorper id. Nullam aliquet malesuada est at dignissim. Pellentesque finibus "
44
44
" sagittis libero nec bibendum. Phasellus dolor ipsum, finibus quis turpis quis, mollis interdum felis." ;
45
45
46
- constexpr std::array patterns = {
47
- " aliquet" sv,
48
- " aliquet malesuada" sv,
46
+ template <size_t Size, bool Last_is_different>
47
+ constexpr auto make_fill_pattern_array () {
48
+ std::array<char , Size> result;
49
+ result.fill (' *' );
50
+
51
+ if constexpr (Last_is_different) {
52
+ result.back () = ' !' ;
53
+ }
54
+
55
+ return result;
56
+ }
57
+
58
+ template <size_t Size, bool Last_is_different>
59
+ constexpr std::array fill_pattern_array = make_fill_pattern_array<Size, Last_is_different>();
60
+
61
+ template <size_t Size, bool Last_is_different>
62
+ constexpr std::string_view fill_pattern_view = fill_pattern_array<Size, Last_is_different>;
63
+
64
+ struct data_and_pattern {
65
+ std::string_view data;
66
+ std::string_view pattern;
67
+ };
68
+
69
+ constexpr data_and_pattern patterns[] = {
70
+ /* 0. Small, closer to end */ {common_src_data, " aliquet" sv},
71
+ /* 1. Large, closer to end */ {common_src_data, " aliquet malesuada" sv},
72
+ /* 2. Small, closer to begin */ {common_src_data, " pulvinar" sv},
73
+ /* 3. Large, closer to begin */ {common_src_data, " dapibus elit interdum" sv},
74
+
75
+ /* 4. Small, evil */ {fill_pattern_view<3000 , false >, fill_pattern_view<7 , true >},
76
+ /* 5. Large, evil */ {fill_pattern_view<3000 , false >, fill_pattern_view<20 , true >},
49
77
};
50
78
51
79
void c_strstr (benchmark::State& state) {
52
- const auto & src_needle = patterns[static_cast <size_t >(state.range ())];
80
+ const auto & src_haystack = patterns[static_cast <size_t >(state.range ())].data ;
81
+ const auto & src_needle = patterns[static_cast <size_t >(state.range ())].pattern ;
53
82
54
83
const std::string haystack (std::begin (src_haystack), std::end (src_haystack));
55
84
const std::string needle (std::begin (src_needle), std::end (src_needle));
@@ -64,7 +93,8 @@ void c_strstr(benchmark::State& state) {
64
93
65
94
template <class T >
66
95
void classic_search (benchmark::State& state) {
67
- const auto & src_needle = patterns[static_cast <size_t >(state.range ())];
96
+ const auto & src_haystack = patterns[static_cast <size_t >(state.range ())].data ;
97
+ const auto & src_needle = patterns[static_cast <size_t >(state.range ())].pattern ;
68
98
69
99
const std::vector<T> haystack (std::begin (src_haystack), std::end (src_haystack));
70
100
const std::vector<T> needle (std::begin (src_needle), std::end (src_needle));
@@ -79,7 +109,8 @@ void classic_search(benchmark::State& state) {
79
109
80
110
template <class T >
81
111
void ranges_search (benchmark::State& state) {
82
- const auto & src_needle = patterns[static_cast <size_t >(state.range ())];
112
+ const auto & src_haystack = patterns[static_cast <size_t >(state.range ())].data ;
113
+ const auto & src_needle = patterns[static_cast <size_t >(state.range ())].pattern ;
83
114
84
115
const std::vector<T> haystack (std::begin (src_haystack), std::end (src_haystack));
85
116
const std::vector<T> needle (std::begin (src_needle), std::end (src_needle));
@@ -94,7 +125,8 @@ void ranges_search(benchmark::State& state) {
94
125
95
126
template <class T >
96
127
void search_default_searcher (benchmark::State& state) {
97
- const auto & src_needle = patterns[static_cast <size_t >(state.range ())];
128
+ const auto & src_haystack = patterns[static_cast <size_t >(state.range ())].data ;
129
+ const auto & src_needle = patterns[static_cast <size_t >(state.range ())].pattern ;
98
130
99
131
const std::vector<T> haystack (std::begin (src_haystack), std::end (src_haystack));
100
132
const std::vector<T> needle (std::begin (src_needle), std::end (src_needle));
@@ -107,26 +139,57 @@ void search_default_searcher(benchmark::State& state) {
107
139
}
108
140
}
109
141
142
+ template <class T >
143
+ void classic_find_end (benchmark::State& state) {
144
+ const auto & src_haystack = patterns[static_cast <size_t >(state.range ())].data ;
145
+ const auto & src_needle = patterns[static_cast <size_t >(state.range ())].pattern ;
146
+
147
+ const std::vector<T> haystack (std::begin (src_haystack), std::end (src_haystack));
148
+ const std::vector<T> needle (std::begin (src_needle), std::end (src_needle));
149
+
150
+ for (auto _ : state) {
151
+ benchmark::DoNotOptimize (haystack);
152
+ benchmark::DoNotOptimize (needle);
153
+ auto res = std::find_end (haystack.begin (), haystack.end (), needle.begin (), needle.end ());
154
+ benchmark::DoNotOptimize (res);
155
+ }
156
+ }
157
+
158
+ template <class T >
159
+ void ranges_find_end (benchmark::State& state) {
160
+ const auto & src_haystack = patterns[static_cast <size_t >(state.range ())].data ;
161
+ const auto & src_needle = patterns[static_cast <size_t >(state.range ())].pattern ;
162
+
163
+ const std::vector<T> haystack (std::begin (src_haystack), std::end (src_haystack));
164
+ const std::vector<T> needle (std::begin (src_needle), std::end (src_needle));
165
+
166
+ for (auto _ : state) {
167
+ benchmark::DoNotOptimize (haystack);
168
+ benchmark::DoNotOptimize (needle);
169
+ auto res = std::ranges::find_end (haystack, needle);
170
+ benchmark::DoNotOptimize (res);
171
+ }
172
+ }
173
+
110
174
void common_args (auto bm) {
111
- bm->Range (0 , patterns. size () - 1 );
175
+ bm->DenseRange (0 , std:: size (patterns ) - 1 , 1 );
112
176
}
113
177
114
178
BENCHMARK (c_strstr)->Apply(common_args);
115
179
116
180
BENCHMARK (classic_search<std::uint8_t >)->Apply(common_args);
117
181
BENCHMARK (classic_search<std::uint16_t >)->Apply(common_args);
118
- BENCHMARK (classic_search<std::uint32_t >)->Apply(common_args);
119
- BENCHMARK (classic_search<std::uint64_t >)->Apply(common_args);
120
182
121
183
BENCHMARK (ranges_search<std::uint8_t >)->Apply(common_args);
122
184
BENCHMARK (ranges_search<std::uint16_t >)->Apply(common_args);
123
- BENCHMARK (ranges_search<std::uint32_t >)->Apply(common_args);
124
- BENCHMARK (ranges_search<std::uint64_t >)->Apply(common_args);
125
185
126
186
BENCHMARK (search_default_searcher<std::uint8_t >)->Apply(common_args);
127
187
BENCHMARK (search_default_searcher<std::uint16_t >)->Apply(common_args);
128
- BENCHMARK (search_default_searcher<std::uint32_t >)->Apply(common_args);
129
- BENCHMARK (search_default_searcher<std::uint64_t >)->Apply(common_args);
130
188
189
+ BENCHMARK (classic_find_end<std::uint8_t >)->Apply(common_args);
190
+ BENCHMARK (classic_find_end<std::uint16_t >)->Apply(common_args);
191
+
192
+ BENCHMARK (ranges_find_end<std::uint8_t >)->Apply(common_args);
193
+ BENCHMARK (ranges_find_end<std::uint16_t >)->Apply(common_args);
131
194
132
195
BENCHMARK_MAIN ();
0 commit comments