1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/strings/str_cat.h"
16
17 #include <cstdint>
18 #include <string>
19
20 #include "benchmark/benchmark.h"
21 #include "absl/strings/substitute.h"
22
23 namespace {
24
25 const char kStringOne[] = "Once Upon A Time, ";
26 const char kStringTwo[] = "There was a std::string benchmark";
27
28 // We want to include negative numbers in the benchmark, so this function
29 // is used to count 0, 1, -1, 2, -2, 3, -3, ...
IncrementAlternatingSign(int i)30 inline int IncrementAlternatingSign(int i) {
31 return i > 0 ? -i : 1 - i;
32 }
33
BM_Sum_By_StrCat(benchmark::State & state)34 void BM_Sum_By_StrCat(benchmark::State& state) {
35 int i = 0;
36 char foo[100];
37 for (auto _ : state) {
38 // NOLINTNEXTLINE(runtime/printf)
39 strcpy(foo, absl::StrCat(kStringOne, i, kStringTwo, i * 65536ULL).c_str());
40 int sum = 0;
41 for (char* f = &foo[0]; *f != 0; ++f) {
42 sum += *f;
43 }
44 benchmark::DoNotOptimize(sum);
45 i = IncrementAlternatingSign(i);
46 }
47 }
48 BENCHMARK(BM_Sum_By_StrCat);
49
BM_StrCat_By_snprintf(benchmark::State & state)50 void BM_StrCat_By_snprintf(benchmark::State& state) {
51 int i = 0;
52 char on_stack[1000];
53 for (auto _ : state) {
54 snprintf(on_stack, sizeof(on_stack), "%s %s:%d", kStringOne, kStringTwo, i);
55 i = IncrementAlternatingSign(i);
56 }
57 }
58 BENCHMARK(BM_StrCat_By_snprintf);
59
BM_StrCat_By_Strings(benchmark::State & state)60 void BM_StrCat_By_Strings(benchmark::State& state) {
61 int i = 0;
62 for (auto _ : state) {
63 std::string result =
64 std::string(kStringOne) + " " + kStringTwo + ":" + absl::StrCat(i);
65 benchmark::DoNotOptimize(result);
66 i = IncrementAlternatingSign(i);
67 }
68 }
69 BENCHMARK(BM_StrCat_By_Strings);
70
BM_StrCat_By_StringOpPlus(benchmark::State & state)71 void BM_StrCat_By_StringOpPlus(benchmark::State& state) {
72 int i = 0;
73 for (auto _ : state) {
74 std::string result = kStringOne;
75 result += " ";
76 result += kStringTwo;
77 result += ":";
78 result += absl::StrCat(i);
79 benchmark::DoNotOptimize(result);
80 i = IncrementAlternatingSign(i);
81 }
82 }
83 BENCHMARK(BM_StrCat_By_StringOpPlus);
84
BM_StrCat_By_StrCat(benchmark::State & state)85 void BM_StrCat_By_StrCat(benchmark::State& state) {
86 int i = 0;
87 for (auto _ : state) {
88 std::string result = absl::StrCat(kStringOne, " ", kStringTwo, ":", i);
89 benchmark::DoNotOptimize(result);
90 i = IncrementAlternatingSign(i);
91 }
92 }
93 BENCHMARK(BM_StrCat_By_StrCat);
94
BM_HexCat_By_StrCat(benchmark::State & state)95 void BM_HexCat_By_StrCat(benchmark::State& state) {
96 int i = 0;
97 for (auto _ : state) {
98 std::string result =
99 absl::StrCat(kStringOne, " ", absl::Hex(int64_t{i} + 0x10000000));
100 benchmark::DoNotOptimize(result);
101 i = IncrementAlternatingSign(i);
102 }
103 }
104 BENCHMARK(BM_HexCat_By_StrCat);
105
BM_HexCat_By_Substitute(benchmark::State & state)106 void BM_HexCat_By_Substitute(benchmark::State& state) {
107 int i = 0;
108 for (auto _ : state) {
109 std::string result = absl::Substitute(
110 "$0 $1", kStringOne, reinterpret_cast<void*>(int64_t{i} + 0x10000000));
111 benchmark::DoNotOptimize(result);
112 i = IncrementAlternatingSign(i);
113 }
114 }
115 BENCHMARK(BM_HexCat_By_Substitute);
116
BM_FloatToString_By_StrCat(benchmark::State & state)117 void BM_FloatToString_By_StrCat(benchmark::State& state) {
118 int i = 0;
119 float foo = 0.0f;
120 for (auto _ : state) {
121 std::string result = absl::StrCat(foo += 1.001f, " != ", int64_t{i});
122 benchmark::DoNotOptimize(result);
123 i = IncrementAlternatingSign(i);
124 }
125 }
126 BENCHMARK(BM_FloatToString_By_StrCat);
127
BM_DoubleToString_By_SixDigits(benchmark::State & state)128 void BM_DoubleToString_By_SixDigits(benchmark::State& state) {
129 int i = 0;
130 double foo = 0.0;
131 for (auto _ : state) {
132 std::string result =
133 absl::StrCat(absl::SixDigits(foo += 1.001), " != ", int64_t{i});
134 benchmark::DoNotOptimize(result);
135 i = IncrementAlternatingSign(i);
136 }
137 }
138 BENCHMARK(BM_DoubleToString_By_SixDigits);
139
140 } // namespace
141