blob: fe8a1c533d9068ad3d4e8032132a16a7dae8d78a [file] [log] [blame]
Sebastian Pop65115202016-12-30 18:01:36 +00001
Samuel Benzaquencfe3d782018-10-30 15:54:22 +00002#include <cstdint>
3#include <new>
4#include <vector>
5
Nico Weberfa647f82019-08-21 01:59:12 +00006#include "CartesianBenchmarks.h"
7#include "GenerateInput.h"
Samuel Benzaquencfe3d782018-10-30 15:54:22 +00008#include "benchmark/benchmark.h"
9#include "test_macros.h"
Sebastian Pop65115202016-12-30 18:01:36 +000010
11constexpr std::size_t MAX_STRING_LEN = 8 << 14;
12
13// Benchmark when there is no match.
14static void BM_StringFindNoMatch(benchmark::State &state) {
15 std::string s1(state.range(0), '-');
16 std::string s2(8, '*');
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000017 for (auto _ : state)
Sebastian Pop65115202016-12-30 18:01:36 +000018 benchmark::DoNotOptimize(s1.find(s2));
19}
20BENCHMARK(BM_StringFindNoMatch)->Range(10, MAX_STRING_LEN);
21
22// Benchmark when the string matches first time.
23static void BM_StringFindAllMatch(benchmark::State &state) {
24 std::string s1(MAX_STRING_LEN, '-');
25 std::string s2(state.range(0), '-');
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000026 for (auto _ : state)
Sebastian Pop65115202016-12-30 18:01:36 +000027 benchmark::DoNotOptimize(s1.find(s2));
28}
29BENCHMARK(BM_StringFindAllMatch)->Range(1, MAX_STRING_LEN);
30
31// Benchmark when the string matches somewhere in the end.
32static void BM_StringFindMatch1(benchmark::State &state) {
33 std::string s1(MAX_STRING_LEN / 2, '*');
34 s1 += std::string(state.range(0), '-');
35 std::string s2(state.range(0), '-');
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000036 for (auto _ : state)
Sebastian Pop65115202016-12-30 18:01:36 +000037 benchmark::DoNotOptimize(s1.find(s2));
38}
39BENCHMARK(BM_StringFindMatch1)->Range(1, MAX_STRING_LEN / 4);
40
41// Benchmark when the string matches somewhere from middle to the end.
42static void BM_StringFindMatch2(benchmark::State &state) {
43 std::string s1(MAX_STRING_LEN / 2, '*');
44 s1 += std::string(state.range(0), '-');
45 s1 += std::string(state.range(0), '*');
46 std::string s2(state.range(0), '-');
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000047 for (auto _ : state)
Sebastian Pop65115202016-12-30 18:01:36 +000048 benchmark::DoNotOptimize(s1.find(s2));
49}
50BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);
51
Eric Fiselier718a8ec2018-07-10 04:11:22 +000052static void BM_StringCtorDefault(benchmark::State &state) {
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000053 for (auto _ : state) {
54 std::string Default;
55 benchmark::DoNotOptimize(Default);
Eric Fiselier718a8ec2018-07-10 04:11:22 +000056 }
57}
58BENCHMARK(BM_StringCtorDefault);
59
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000060enum class Length { Empty, Small, Large, Huge };
61struct AllLengths : EnumValuesAsTuple<AllLengths, Length, 4> {
62 static constexpr const char* Names[] = {"Empty", "Small", "Large", "Huge"};
63};
64
65enum class Opacity { Opaque, Transparent };
66struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
67 static constexpr const char* Names[] = {"Opaque", "Transparent"};
68};
69
70enum class DiffType { Control, ChangeFirst, ChangeMiddle, ChangeLast };
71struct AllDiffTypes : EnumValuesAsTuple<AllDiffTypes, DiffType, 4> {
72 static constexpr const char* Names[] = {"Control", "ChangeFirst",
73 "ChangeMiddle", "ChangeLast"};
74};
75
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +000076static constexpr char SmallStringLiteral[] = "012345678";
Samuel Benzaquen935e0092019-03-21 16:06:15 +000077
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000078TEST_ALWAYS_INLINE const char* getSmallString(DiffType D) {
79 switch (D) {
80 case DiffType::Control:
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +000081 return SmallStringLiteral;
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000082 case DiffType::ChangeFirst:
Samuel Benzaquen935e0092019-03-21 16:06:15 +000083 return "-12345678";
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000084 case DiffType::ChangeMiddle:
Samuel Benzaquen935e0092019-03-21 16:06:15 +000085 return "0123-5678";
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000086 case DiffType::ChangeLast:
Samuel Benzaquen935e0092019-03-21 16:06:15 +000087 return "01234567-";
Eric Fiselier718a8ec2018-07-10 04:11:22 +000088 }
89}
Eric Fiselier718a8ec2018-07-10 04:11:22 +000090
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +000091static constexpr char LargeStringLiteral[] =
92 "012345678901234567890123456789012345678901234567890123456789012";
93
Samuel Benzaquencfe3d782018-10-30 15:54:22 +000094TEST_ALWAYS_INLINE const char* getLargeString(DiffType D) {
95#define LARGE_STRING_FIRST "123456789012345678901234567890"
96#define LARGE_STRING_SECOND "234567890123456789012345678901"
97 switch (D) {
98 case DiffType::Control:
99 return "0" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "2";
100 case DiffType::ChangeFirst:
101 return "-" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "2";
102 case DiffType::ChangeMiddle:
103 return "0" LARGE_STRING_FIRST "-" LARGE_STRING_SECOND "2";
104 case DiffType::ChangeLast:
105 return "0" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "-";
106 }
107}
108
109TEST_ALWAYS_INLINE const char* getHugeString(DiffType D) {
110#define HUGE_STRING0 "0123456789"
111#define HUGE_STRING1 HUGE_STRING0 HUGE_STRING0 HUGE_STRING0 HUGE_STRING0
112#define HUGE_STRING2 HUGE_STRING1 HUGE_STRING1 HUGE_STRING1 HUGE_STRING1
113#define HUGE_STRING3 HUGE_STRING2 HUGE_STRING2 HUGE_STRING2 HUGE_STRING2
114#define HUGE_STRING4 HUGE_STRING3 HUGE_STRING3 HUGE_STRING3 HUGE_STRING3
115 switch (D) {
116 case DiffType::Control:
117 return "0123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "0123456789";
118 case DiffType::ChangeFirst:
119 return "-123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "0123456789";
120 case DiffType::ChangeMiddle:
121 return "0123456789" HUGE_STRING4 "01234-6789" HUGE_STRING4 "0123456789";
122 case DiffType::ChangeLast:
123 return "0123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "012345678-";
124 }
125}
126
Eric Fiselierc05a01c2020-01-07 16:31:06 -0500127TEST_ALWAYS_INLINE const char* getString(Length L,
128 DiffType D = DiffType::Control) {
129 switch (L) {
130 case Length::Empty:
131 return "";
132 case Length::Small:
133 return getSmallString(D);
134 case Length::Large:
135 return getLargeString(D);
136 case Length::Huge:
137 return getHugeString(D);
138 }
139}
140
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000141TEST_ALWAYS_INLINE std::string makeString(Length L,
142 DiffType D = DiffType::Control,
143 Opacity O = Opacity::Transparent) {
144 switch (L) {
145 case Length::Empty:
146 return maybeOpaque("", O == Opacity::Opaque);
147 case Length::Small:
148 return maybeOpaque(getSmallString(D), O == Opacity::Opaque);
149 case Length::Large:
150 return maybeOpaque(getLargeString(D), O == Opacity::Opaque);
151 case Length::Huge:
152 return maybeOpaque(getHugeString(D), O == Opacity::Opaque);
153 }
154}
155
156template <class Length, class Opaque>
157struct StringConstructDestroyCStr {
158 static void run(benchmark::State& state) {
159 for (auto _ : state) {
160 benchmark::DoNotOptimize(
161 makeString(Length(), DiffType::Control, Opaque()));
162 }
163 }
164
165 static std::string name() {
166 return "BM_StringConstructDestroyCStr" + Length::name() + Opaque::name();
167 }
168};
169
170template <class Length, bool MeasureCopy, bool MeasureDestroy>
171static void StringCopyAndDestroy(benchmark::State& state) {
172 static constexpr size_t NumStrings = 1024;
173 auto Orig = makeString(Length());
174 std::aligned_storage<sizeof(std::string)>::type Storage[NumStrings];
175
176 while (state.KeepRunningBatch(NumStrings)) {
177 if (!MeasureCopy)
178 state.PauseTiming();
179 for (size_t I = 0; I < NumStrings; ++I) {
180 ::new (static_cast<void*>(Storage + I)) std::string(Orig);
181 }
182 if (!MeasureCopy)
183 state.ResumeTiming();
184 if (!MeasureDestroy)
185 state.PauseTiming();
186 for (size_t I = 0; I < NumStrings; ++I) {
187 using S = std::string;
188 reinterpret_cast<S*>(Storage + I)->~S();
189 }
190 if (!MeasureDestroy)
191 state.ResumeTiming();
192 }
193}
194
195template <class Length>
196struct StringCopy {
197 static void run(benchmark::State& state) {
198 StringCopyAndDestroy<Length, true, false>(state);
199 }
200
201 static std::string name() { return "BM_StringCopy" + Length::name(); }
202};
203
204template <class Length>
205struct StringDestroy {
206 static void run(benchmark::State& state) {
207 StringCopyAndDestroy<Length, false, true>(state);
208 }
209
210 static std::string name() { return "BM_StringDestroy" + Length::name(); }
211};
212
213template <class Length>
214struct StringMove {
215 static void run(benchmark::State& state) {
216 // Keep two object locations and move construct back and forth.
Eric Fiselier44966cf2018-11-13 19:16:19 +0000217 std::aligned_storage<sizeof(std::string), alignof(std::string)>::type Storage[2];
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000218 using S = std::string;
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000219 size_t I = 0;
Eric Fiselier44966cf2018-11-13 19:16:19 +0000220 S *newS = new (static_cast<void*>(Storage)) std::string(makeString(Length()));
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000221 for (auto _ : state) {
222 // Switch locations.
223 I ^= 1;
224 benchmark::DoNotOptimize(Storage);
225 // Move construct into the new location,
Eric Fiselier44966cf2018-11-13 19:16:19 +0000226 S *tmpS = new (static_cast<void*>(Storage + I)) S(std::move(*newS));
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000227 // then destroy the old one.
Eric Fiselier44966cf2018-11-13 19:16:19 +0000228 newS->~S();
229 newS = tmpS;
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000230 }
Eric Fiselier44966cf2018-11-13 19:16:19 +0000231 newS->~S();
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000232 }
233
234 static std::string name() { return "BM_StringMove" + Length::name(); }
235};
236
Eric Fiselierc05a01c2020-01-07 16:31:06 -0500237template <class Length, class Opaque>
238struct StringResizeDefaultInit {
239 static void run(benchmark::State& state) {
240 constexpr bool opaque = Opaque{} == Opacity::Opaque;
241 constexpr int kNumStrings = 4 << 10;
242 size_t length = makeString(Length()).size();
243 std::string strings[kNumStrings];
244 while (state.KeepRunningBatch(kNumStrings)) {
245 state.PauseTiming();
246 for (int i = 0; i < kNumStrings; ++i) {
247 std::string().swap(strings[i]);
248 }
249 benchmark::DoNotOptimize(strings);
250 state.ResumeTiming();
251 for (int i = 0; i < kNumStrings; ++i) {
252 strings[i].__resize_default_init(maybeOpaque(length, opaque));
253 }
254 }
255 }
256
257 static std::string name() {
258 return "BM_StringResizeDefaultInit" + Length::name() + Opaque::name();
259 }
260};
261
262template <class Length, class Opaque>
263struct StringAssignStr {
264 static void run(benchmark::State& state) {
265 constexpr bool opaque = Opaque{} == Opacity::Opaque;
266 constexpr int kNumStrings = 4 << 10;
267 std::string src = makeString(Length());
268 std::string strings[kNumStrings];
269 while (state.KeepRunningBatch(kNumStrings)) {
270 state.PauseTiming();
271 for (int i = 0; i < kNumStrings; ++i) {
272 std::string().swap(strings[i]);
273 }
274 benchmark::DoNotOptimize(strings);
275 state.ResumeTiming();
276 for (int i = 0; i < kNumStrings; ++i) {
277 strings[i] = *maybeOpaque(&src, opaque);
278 }
279 }
280 }
281
282 static std::string name() {
283 return "BM_StringAssignStr" + Length::name() + Opaque::name();
284 }
285};
286
287template <class Length, class Opaque>
288struct StringAssignAsciiz {
289 static void run(benchmark::State& state) {
290 constexpr bool opaque = Opaque{} == Opacity::Opaque;
291 constexpr int kNumStrings = 4 << 10;
292 std::string strings[kNumStrings];
293 while (state.KeepRunningBatch(kNumStrings)) {
294 state.PauseTiming();
295 for (int i = 0; i < kNumStrings; ++i) {
296 std::string().swap(strings[i]);
297 }
298 benchmark::DoNotOptimize(strings);
299 state.ResumeTiming();
300 for (int i = 0; i < kNumStrings; ++i) {
301 strings[i] = maybeOpaque(getString(Length()), opaque);
302 }
303 }
304 }
305
306 static std::string name() {
307 return "BM_StringAssignAsciiz" + Length::name() + Opaque::name();
308 }
309};
310
311template <class Opaque>
312struct StringAssignAsciizMix {
313 static void run(benchmark::State& state) {
314 constexpr auto O = Opaque{};
315 constexpr auto D = DiffType::Control;
316 constexpr int kNumStrings = 4 << 10;
317 std::string strings[kNumStrings];
318 while (state.KeepRunningBatch(kNumStrings)) {
319 state.PauseTiming();
320 for (int i = 0; i < kNumStrings; ++i) {
321 std::string().swap(strings[i]);
322 }
323 benchmark::DoNotOptimize(strings);
324 state.ResumeTiming();
325 for (int i = 0; i < kNumStrings - 7; i += 8) {
326 strings[i + 0] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
327 strings[i + 1] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
328 strings[i + 2] = maybeOpaque(getLargeString(D), O == Opacity::Opaque);
329 strings[i + 3] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
330 strings[i + 4] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
331 strings[i + 5] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
332 strings[i + 6] = maybeOpaque(getLargeString(D), O == Opacity::Opaque);
333 strings[i + 7] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
334 }
335 }
336 }
337
338 static std::string name() {
339 return "BM_StringAssignAsciizMix" + Opaque::name();
340 }
341};
342
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000343enum class Relation { Eq, Less, Compare };
344struct AllRelations : EnumValuesAsTuple<AllRelations, Relation, 3> {
345 static constexpr const char* Names[] = {"Eq", "Less", "Compare"};
346};
347
348template <class Rel, class LHLength, class RHLength, class DiffType>
349struct StringRelational {
350 static void run(benchmark::State& state) {
351 auto Lhs = makeString(RHLength());
352 auto Rhs = makeString(LHLength(), DiffType());
353 for (auto _ : state) {
354 benchmark::DoNotOptimize(Lhs);
355 benchmark::DoNotOptimize(Rhs);
356 switch (Rel()) {
357 case Relation::Eq:
358 benchmark::DoNotOptimize(Lhs == Rhs);
359 break;
360 case Relation::Less:
361 benchmark::DoNotOptimize(Lhs < Rhs);
362 break;
363 case Relation::Compare:
364 benchmark::DoNotOptimize(Lhs.compare(Rhs));
365 break;
366 }
367 }
368 }
369
370 static bool skip() {
371 // Eq is commutative, so skip half the matrix.
372 if (Rel() == Relation::Eq && LHLength() > RHLength())
373 return true;
374 // We only care about control when the lengths differ.
375 if (LHLength() != RHLength() && DiffType() != ::DiffType::Control)
376 return true;
377 // For empty, only control matters.
378 if (LHLength() == Length::Empty && DiffType() != ::DiffType::Control)
379 return true;
380 return false;
381 }
382
383 static std::string name() {
384 return "BM_StringRelational" + Rel::name() + LHLength::name() +
385 RHLength::name() + DiffType::name();
386 }
387};
388
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000389template <class Rel, class LHLength, class RHLength, class DiffType>
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000390struct StringRelationalLiteral {
391 static void run(benchmark::State& state) {
392 auto Lhs = makeString(LHLength(), DiffType());
393 for (auto _ : state) {
394 benchmark::DoNotOptimize(Lhs);
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000395 constexpr const char* Literal = RHLength::value == Length::Empty
396 ? ""
397 : RHLength::value == Length::Small
398 ? SmallStringLiteral
399 : LargeStringLiteral;
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000400 switch (Rel()) {
401 case Relation::Eq:
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000402 benchmark::DoNotOptimize(Lhs == Literal);
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000403 break;
404 case Relation::Less:
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000405 benchmark::DoNotOptimize(Lhs < Literal);
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000406 break;
407 case Relation::Compare:
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000408 benchmark::DoNotOptimize(Lhs.compare(Literal));
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000409 break;
410 }
411 }
412 }
413
414 static bool skip() {
415 // Doesn't matter how they differ if they have different size.
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000416 if (LHLength() != RHLength() && DiffType() != ::DiffType::Control)
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000417 return true;
418 // We don't need huge. Doensn't give anything different than Large.
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000419 if (LHLength() == Length::Huge || RHLength() == Length::Huge)
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000420 return true;
421 return false;
422 }
423
424 static std::string name() {
425 return "BM_StringRelationalLiteral" + Rel::name() + LHLength::name() +
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000426 RHLength::name() + DiffType::name();
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000427 }
428};
429
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000430enum class Depth { Shallow, Deep };
431struct AllDepths : EnumValuesAsTuple<AllDepths, Depth, 2> {
432 static constexpr const char* Names[] = {"Shallow", "Deep"};
433};
434
435enum class Temperature { Hot, Cold };
436struct AllTemperatures : EnumValuesAsTuple<AllTemperatures, Temperature, 2> {
437 static constexpr const char* Names[] = {"Hot", "Cold"};
438};
439
440template <class Temperature, class Depth, class Length>
441struct StringRead {
442 void run(benchmark::State& state) const {
443 static constexpr size_t NumStrings =
444 Temperature() == ::Temperature::Hot
445 ? 1 << 10
446 : /* Enough strings to overflow the cache */ 1 << 20;
447 static_assert((NumStrings & (NumStrings - 1)) == 0,
448 "NumStrings should be a power of two to reduce overhead.");
449
450 std::vector<std::string> Values(NumStrings, makeString(Length()));
451 size_t I = 0;
452 for (auto _ : state) {
453 // Jump long enough to defeat cache locality, and use a value that is
454 // coprime with NumStrings to ensure we visit every element.
455 I = (I + 17) % NumStrings;
456 const auto& V = Values[I];
457
458 // Read everything first. Escaping data() through DoNotOptimize might
459 // cause the compiler to have to recalculate information about `V` due to
460 // aliasing.
461 const char* const Data = V.data();
462 const size_t Size = V.size();
463 benchmark::DoNotOptimize(Data);
464 benchmark::DoNotOptimize(Size);
465 if (Depth() == ::Depth::Deep) {
466 // Read into the payload. This mainly shows the benefit of SSO when the
467 // data is cold.
468 benchmark::DoNotOptimize(*Data);
469 }
470 }
471 }
472
473 static bool skip() {
474 // Huge does not give us anything that Large doesn't have. Skip it.
475 if (Length() == ::Length::Huge) {
476 return true;
477 }
478 return false;
479 }
480
481 std::string name() const {
482 return "BM_StringRead" + Temperature::name() + Depth::name() +
483 Length::name();
484 }
485};
486
487void sanityCheckGeneratedStrings() {
488 for (auto Lhs : {Length::Empty, Length::Small, Length::Large, Length::Huge}) {
489 const auto LhsString = makeString(Lhs);
490 for (auto Rhs :
491 {Length::Empty, Length::Small, Length::Large, Length::Huge}) {
492 if (Lhs > Rhs)
493 continue;
494 const auto RhsString = makeString(Rhs);
495
496 // The smaller one must be a prefix of the larger one.
497 if (RhsString.find(LhsString) != 0) {
498 fprintf(stderr, "Invalid autogenerated strings for sizes (%d,%d).\n",
499 static_cast<int>(Lhs), static_cast<int>(Rhs));
500 std::abort();
501 }
502 }
503 }
504 // Verify the autogenerated diffs
505 for (auto L : {Length::Small, Length::Large, Length::Huge}) {
506 const auto Control = makeString(L);
507 const auto Verify = [&](std::string Exp, size_t Pos) {
508 // Only change on the Pos char.
509 if (Control[Pos] != Exp[Pos]) {
510 Exp[Pos] = Control[Pos];
511 if (Control == Exp)
512 return;
513 }
514 fprintf(stderr, "Invalid autogenerated diff with size %d\n",
515 static_cast<int>(L));
516 std::abort();
517 };
518 Verify(makeString(L, DiffType::ChangeFirst), 0);
519 Verify(makeString(L, DiffType::ChangeMiddle), Control.size() / 2);
520 Verify(makeString(L, DiffType::ChangeLast), Control.size() - 1);
521 }
522}
523
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000524// Some small codegen thunks to easily see generated code.
525bool StringEqString(const std::string& a, const std::string& b) {
526 return a == b;
527}
528bool StringEqCStr(const std::string& a, const char* b) { return a == b; }
529bool CStrEqString(const char* a, const std::string& b) { return a == b; }
530bool StringEqCStrLiteralEmpty(const std::string& a) {
531 return a == "";
532}
533bool StringEqCStrLiteralSmall(const std::string& a) {
534 return a == SmallStringLiteral;
535}
536bool StringEqCStrLiteralLarge(const std::string& a) {
537 return a == LargeStringLiteral;
538}
539
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000540int main(int argc, char** argv) {
541 benchmark::Initialize(&argc, argv);
542 if (benchmark::ReportUnrecognizedArguments(argc, argv))
543 return 1;
544
545 sanityCheckGeneratedStrings();
546
547 makeCartesianProductBenchmark<StringConstructDestroyCStr, AllLengths,
548 AllOpacity>();
Eric Fiselierc05a01c2020-01-07 16:31:06 -0500549
550 makeCartesianProductBenchmark<StringAssignStr, AllLengths, AllOpacity>();
551 makeCartesianProductBenchmark<StringAssignAsciiz, AllLengths, AllOpacity>();
552 makeCartesianProductBenchmark<StringAssignAsciizMix, AllOpacity>();
553
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000554 makeCartesianProductBenchmark<StringCopy, AllLengths>();
555 makeCartesianProductBenchmark<StringMove, AllLengths>();
556 makeCartesianProductBenchmark<StringDestroy, AllLengths>();
Eric Fiselierc05a01c2020-01-07 16:31:06 -0500557 makeCartesianProductBenchmark<StringResizeDefaultInit, AllLengths,
558 AllOpacity>();
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000559 makeCartesianProductBenchmark<StringRelational, AllRelations, AllLengths,
560 AllLengths, AllDiffTypes>();
Samuel Benzaquen935e0092019-03-21 16:06:15 +0000561 makeCartesianProductBenchmark<StringRelationalLiteral, AllRelations,
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000562 AllLengths, AllLengths, AllDiffTypes>();
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000563 makeCartesianProductBenchmark<StringRead, AllTemperatures, AllDepths,
564 AllLengths>();
565 benchmark::RunSpecifiedBenchmarks();
Samuel Benzaquen42a76dc2019-04-03 17:40:51 +0000566
567 if (argc < 0) {
568 // ODR-use the functions to force them being generated in the binary.
569 auto functions = std::make_tuple(
570 StringEqString, StringEqCStr, CStrEqString, StringEqCStrLiteralEmpty,
571 StringEqCStrLiteralSmall, StringEqCStrLiteralLarge);
572 printf("%p", &functions);
573 }
Samuel Benzaquencfe3d782018-10-30 15:54:22 +0000574}