substitute_benchmark.cc (5413B)
1 // Copyright 2020 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 <cstddef> 16 #include <cstdint> 17 #include <string> 18 19 #include "absl/strings/str_cat.h" 20 #include "absl/strings/substitute.h" 21 #include "benchmark/benchmark.h" 22 23 namespace { 24 25 void BM_Substitute(benchmark::State& state) { 26 std::string s(state.range(0), 'x'); 27 int64_t bytes = 0; 28 for (auto _ : state) { 29 std::string result = absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", s, 30 s, s, s, s, s, s, s, s, s); 31 bytes += result.size(); 32 } 33 state.SetBytesProcessed(bytes); 34 } 35 BENCHMARK(BM_Substitute)->Range(0, 1024); 36 37 // Like BM_Substitute, but use char* strings (which must then be copied 38 // to STL strings) for all parameters. This demonstrates that it is faster 39 // to use absl::Substitute() even if your inputs are char* strings. 40 void BM_SubstituteCstr(benchmark::State& state) { 41 std::string s(state.range(0), 'x'); 42 int64_t bytes = 0; 43 for (auto _ : state) { 44 std::string result = 45 absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", s.c_str(), 46 s.c_str(), s.c_str(), s.c_str(), s.c_str(), s.c_str(), 47 s.c_str(), s.c_str(), s.c_str(), s.c_str()); 48 bytes += result.size(); 49 } 50 state.SetBytesProcessed(bytes); 51 } 52 BENCHMARK(BM_SubstituteCstr)->Range(0, 1024); 53 54 // For comparison with BM_Substitute. 55 void BM_StringPrintf(benchmark::State& state) { 56 std::string s(state.range(0), 'x'); 57 int64_t bytes = 0; 58 for (auto _ : state) { 59 std::string result = absl::StrCat(s, " ", s, " ", s, " ", s, " ", s, " ", s, 60 " ", s, " ", s, " ", s, " ", s); 61 bytes += result.size(); 62 } 63 state.SetBytesProcessed(bytes); 64 } 65 BENCHMARK(BM_StringPrintf)->Range(0, 1024); 66 67 // Benchmark using absl::Substitute() together with SimpleItoa() to print 68 // numbers. This demonstrates that absl::Substitute() is faster than 69 // StringPrintf() even when the inputs are numbers. 70 void BM_SubstituteNumber(benchmark::State& state) { 71 const int n = state.range(0); 72 int64_t bytes = 0; 73 for (auto _ : state) { 74 std::string result = 75 absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", n, n + 1, n + 2, 76 n + 3, n + 4, n + 5, n + 6, n + 7, n + 8, n + 9); 77 bytes += result.size(); 78 } 79 state.SetBytesProcessed(bytes); 80 } 81 BENCHMARK(BM_SubstituteNumber)->Arg(0)->Arg(1 << 20); 82 83 // For comparison with BM_SubstituteNumber. 84 void BM_StrCatNumber(benchmark::State& state) { 85 const int n = state.range(0); 86 int64_t bytes = 0; 87 for (auto _ : state) { 88 std::string result = 89 absl::StrCat(n, " ", n + 1, " ", n + 2, " ", n + 3, " ", n + 4, " ", 90 n + 5, " ", n + 6, " ", n + 7, " ", n + 8, " ", n + 9); 91 bytes += result.size(); 92 } 93 state.SetBytesProcessed(bytes); 94 } 95 BENCHMARK(BM_StrCatNumber)->Arg(0)->Arg(1 << 20); 96 97 // Benchmark using absl::Substitute() with a single substitution, to test the 98 // speed at which it copies simple text. Even in this case, it's faster 99 // that StringPrintf(). 100 void BM_SubstituteSimpleText(benchmark::State& state) { 101 std::string s(state.range(0), 'x'); 102 int64_t bytes = 0; 103 for (auto _ : state) { 104 std::string result = absl::Substitute("$0", s.c_str()); 105 bytes += result.size(); 106 } 107 state.SetBytesProcessed(bytes); 108 } 109 BENCHMARK(BM_SubstituteSimpleText)->Range(0, 1024); 110 111 // For comparison with BM_SubstituteSimpleText. 112 void BM_StrCatSimpleText(benchmark::State& state) { 113 std::string s(state.range(0), 'x'); 114 int64_t bytes = 0; 115 for (auto _ : state) { 116 std::string result = absl::StrCat("", s); 117 bytes += result.size(); 118 } 119 state.SetBytesProcessed(bytes); 120 } 121 BENCHMARK(BM_StrCatSimpleText)->Range(0, 1024); 122 123 std::string MakeFormatByDensity(int density, bool subs_mode) { 124 std::string format((2 + density) * 10, 'x'); 125 for (size_t i = 0; i < 10; ++i) { 126 format[density * i] = subs_mode ? '$' : '%'; 127 format[density * i + 1] = subs_mode ? ('0' + i) : 's'; 128 } 129 return format; 130 } 131 132 void BM_SubstituteDensity(benchmark::State& state) { 133 const std::string s(10, 'x'); 134 const std::string format = MakeFormatByDensity(state.range(0), true); 135 int64_t bytes = 0; 136 for (auto _ : state) { 137 std::string result = absl::Substitute(format, s, s, s, s, s, s, s, s, s, s); 138 bytes += result.size(); 139 } 140 state.SetBytesProcessed(bytes); 141 } 142 BENCHMARK(BM_SubstituteDensity)->Range(0, 256); 143 144 void BM_StrCatDensity(benchmark::State& state) { 145 const std::string s(10, 'x'); 146 const std::string format(state.range(0), 'x'); 147 int64_t bytes = 0; 148 for (auto _ : state) { 149 std::string result = 150 absl::StrCat(s, format, s, format, s, format, s, format, s, format, s, 151 format, s, format, s, format, s, format, s, format); 152 bytes += result.size(); 153 } 154 state.SetBytesProcessed(bytes); 155 } 156 BENCHMARK(BM_StrCatDensity)->Range(0, 256); 157 158 } // namespace