22 #include <unordered_set> 25 #include "benchmark/benchmark.h" 43 for (
auto _ : state) {
44 benchmark::DoNotOptimize(a == b);
48 void BM_EqualIdentical(benchmark::State& state) {
49 std::string x(state.range(0),
'a');
50 DoEqualityComparisons(state, x, x);
52 BENCHMARK(BM_EqualIdentical)->DenseRange(0, 3)->Range(4, 1 << 10);
54 void BM_EqualSame(benchmark::State& state) {
55 std::string x(state.range(0),
'a');
57 DoEqualityComparisons(state, x, y);
59 BENCHMARK(BM_EqualSame)
67 void BM_EqualDifferent(benchmark::State& state) {
68 const int len = state.range(0);
69 std::string x(len,
'a');
74 DoEqualityComparisons(state, x, y);
76 BENCHMARK(BM_EqualDifferent)->DenseRange(0, 3)->Range(4, 1 << 10);
86 void DoConstantSizeInlinedEqualityComparisons(benchmark::State& state,
88 for (
auto _ : state) {
89 benchmark::DoNotOptimize(a ==
"aaa");
90 benchmark::DoNotOptimize(a ==
"bbb");
91 benchmark::DoNotOptimize(a ==
"ccc");
92 benchmark::DoNotOptimize(a ==
"ddd");
93 benchmark::DoNotOptimize(a ==
"eee");
94 benchmark::DoNotOptimize(a ==
"fff");
95 benchmark::DoNotOptimize(a ==
"ggg");
96 benchmark::DoNotOptimize(a ==
"hhh");
99 void BM_EqualConstantSizeInlined(benchmark::State& state) {
100 std::string x(state.range(0),
'a');
101 DoConstantSizeInlinedEqualityComparisons(state, x);
105 BENCHMARK(BM_EqualConstantSizeInlined)->DenseRange(2, 4);
111 void DoConstantSizeNonInlinedEqualityComparisons(benchmark::State& state,
113 for (
auto _ : state) {
115 benchmark::DoNotOptimize(NonInlinedEq(a,
"aaa"));
116 benchmark::DoNotOptimize(NonInlinedEq(a,
"bbb"));
117 benchmark::DoNotOptimize(NonInlinedEq(a,
"ccc"));
118 benchmark::DoNotOptimize(NonInlinedEq(a,
"ddd"));
119 benchmark::DoNotOptimize(NonInlinedEq(a,
"eee"));
120 benchmark::DoNotOptimize(NonInlinedEq(a,
"fff"));
121 benchmark::DoNotOptimize(NonInlinedEq(a,
"ggg"));
122 benchmark::DoNotOptimize(NonInlinedEq(a,
"hhh"));
126 void BM_EqualConstantSizeNonInlined(benchmark::State& state) {
127 std::string x(state.range(0),
'a');
128 DoConstantSizeNonInlinedEqualityComparisons(state, x);
132 BENCHMARK(BM_EqualConstantSizeNonInlined)->DenseRange(2, 4);
134 void BM_CompareSame(benchmark::State& state) {
135 const int len = state.range(0);
137 for (
int i = 0;
i <
len;
i++) {
144 for (
auto _ : state) {
145 benchmark::DoNotOptimize(a.
compare(b));
148 BENCHMARK(BM_CompareSame)->DenseRange(0, 3)->Range(4, 1 << 10);
150 void BM_find_string_view_len_one(benchmark::State& state) {
151 std::string haystack(state.range(0),
'0');
153 for (
auto _ : state) {
154 benchmark::DoNotOptimize(s.find(
"x"));
157 BENCHMARK(BM_find_string_view_len_one)->Range(1, 1 << 20);
159 void BM_find_string_view_len_two(benchmark::State& state) {
160 std::string haystack(state.range(0),
'0');
162 for (
auto _ : state) {
163 benchmark::DoNotOptimize(s.find(
"xx"));
166 BENCHMARK(BM_find_string_view_len_two)->Range(1, 1 << 20);
168 void BM_find_one_char(benchmark::State& state) {
169 std::string haystack(state.range(0),
'0');
171 for (
auto _ : state) {
172 benchmark::DoNotOptimize(s.find(
'x'));
175 BENCHMARK(BM_find_one_char)->Range(1, 1 << 20);
177 void BM_rfind_one_char(benchmark::State& state) {
178 std::string haystack(state.range(0),
'0');
180 for (
auto _ : state) {
181 benchmark::DoNotOptimize(s.rfind(
'x'));
184 BENCHMARK(BM_rfind_one_char)->Range(1, 1 << 20);
186 void BM_worst_case_find_first_of(benchmark::State& state,
int haystack_len) {
187 const int needle_len = state.range(0);
189 for (
int i = 0;
i < needle_len; ++
i) {
192 std::string haystack(haystack_len,
'0');
195 for (
auto _ : state) {
196 benchmark::DoNotOptimize(s.find_first_of(needle));
200 void BM_find_first_of_short(benchmark::State& state) {
201 BM_worst_case_find_first_of(state, 10);
204 void BM_find_first_of_medium(benchmark::State& state) {
205 BM_worst_case_find_first_of(state, 100);
208 void BM_find_first_of_long(benchmark::State& state) {
209 BM_worst_case_find_first_of(state, 1000);
212 BENCHMARK(BM_find_first_of_short)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32);
213 BENCHMARK(BM_find_first_of_medium)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32);
214 BENCHMARK(BM_find_first_of_long)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32);
216 struct EasyMap :
public std::map<absl::string_view, uint64_t> {
217 explicit EasyMap(
size_t) {}
226 template <
typename Map,
int WordsPerKey>
227 void StringViewMapBenchmark(benchmark::State& state) {
228 const int table_size = state.range(0);
229 const double kFractionOfKeysThatAreHot = 0.2;
230 const int kNumLookupsOfHotKeys = 20;
231 const int kNumLookupsOfColdKeys = 1;
232 const char* words[] = {
"the",
"quick",
"brown",
"fox",
"jumped",
233 "over",
"the",
"lazy",
"dog",
"and",
234 "found",
"a",
"large",
"mushroom",
"and",
235 "a",
"couple",
"crickets",
"eating",
"pie"};
237 std::random_device r;
238 std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()});
239 std::mt19937 rng(seed);
240 std::vector<std::string>
keys(table_size);
241 std::vector<int> all_indices;
242 const int kBlockSize = 1 << 12;
243 std::unordered_set<std::string> t(kBlockSize);
244 std::uniform_int_distribution<int> uniform(0,
ABSL_ARRAYSIZE(words) - 1);
245 for (
int i = 0;
i < table_size;
i++) {
246 all_indices.push_back(
i);
249 for (
int j = 0; j < WordsPerKey; j++) {
252 }
while (!t.insert(
keys[
i]).second);
257 std::shuffle(all_indices.begin(), all_indices.end(), rng);
258 const int num_hot = table_size * kFractionOfKeysThatAreHot;
259 const int num_cold = table_size - num_hot;
260 std::vector<int> hot_indices(all_indices.begin(),
261 all_indices.begin() + num_hot);
262 std::vector<int> indices;
263 for (
int i = 0;
i < kNumLookupsOfColdKeys;
i++) {
264 indices.insert(indices.end(), all_indices.begin(), all_indices.end());
266 for (
int i = 0;
i < kNumLookupsOfHotKeys - kNumLookupsOfColdKeys;
i++) {
267 indices.insert(indices.end(), hot_indices.begin(), hot_indices.end());
269 std::shuffle(indices.begin(), indices.end(), rng);
271 num_cold * kNumLookupsOfColdKeys + num_hot * kNumLookupsOfHotKeys ==
277 std::vector<std::string> test_strings(indices.size());
278 for (
int i = 0;
i < indices.size();
i++) {
279 test_strings[
i] =
keys[indices[
i]];
284 for (
auto _ : state) {
286 for (
int i = 0;
i < table_size;
i++) {
291 for (
int i = 0;
i < indices.size();
i++) {
292 sum += h[test_strings[
i]];
294 benchmark::DoNotOptimize(sum);
298 void BM_StdMap_4(benchmark::State& state) {
299 StringViewMapBenchmark<EasyMap, 4>(state);
301 BENCHMARK(BM_StdMap_4)->Range(1 << 10, 1 << 16);
303 void BM_StdMap_8(benchmark::State& state) {
304 StringViewMapBenchmark<EasyMap, 8>(state);
306 BENCHMARK(BM_StdMap_8)->Range(1 << 10, 1 << 16);
308 void BM_CopyToStringNative(benchmark::State& state) {
309 std::string src(state.range(0),
'x');
312 for (
auto _ : state) {
313 dst.assign(sv.begin(), sv.end());
316 BENCHMARK(BM_CopyToStringNative)->Range(1 << 3, 1 << 12);
318 void BM_AppendToStringNative(benchmark::State& state) {
319 std::string src(state.range(0),
'x');
322 for (
auto _ : state) {
324 dst.insert(dst.end(), sv.begin(), sv.end());
327 BENCHMARK(BM_AppendToStringNative)->Range(1 << 3, 1 << 12);
void StrAppend(std::string *dest, const AlphaNum &a)
auto keys(const Set &s) -> std::vector< typename std::decay< typename Set::key_type >::type >
#define ABSL_RAW_CHECK(condition, message)
#define ABSL_ATTRIBUTE_NOINLINE
#define ABSL_ARRAYSIZE(array)
int compare(string_view x) const noexcept