| // Copyright 2020 The Abseil Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <string> |
| |
| #include "absl/strings/str_cat.h" |
| #include "absl/strings/substitute.h" |
| #include "benchmark/benchmark.h" |
| |
| namespace { |
| |
| void BM_Substitute(benchmark::State& state) { |
| std::string s(state.range(0), 'x'); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", s, |
| s, s, s, s, s, s, s, s, s); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_Substitute)->Range(0, 1024); |
| |
| // Like BM_Substitute, but use char* strings (which must then be copied |
| // to STL strings) for all parameters. This demonstrates that it is faster |
| // to use absl::Substitute() even if your inputs are char* strings. |
| void BM_SubstituteCstr(benchmark::State& state) { |
| std::string s(state.range(0), 'x'); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = |
| absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", s.c_str(), |
| s.c_str(), s.c_str(), s.c_str(), s.c_str(), s.c_str(), |
| s.c_str(), s.c_str(), s.c_str(), s.c_str()); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_SubstituteCstr)->Range(0, 1024); |
| |
| // For comparison with BM_Substitute. |
| void BM_StringPrintf(benchmark::State& state) { |
| std::string s(state.range(0), 'x'); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = absl::StrCat(s, " ", s, " ", s, " ", s, " ", s, " ", s, |
| " ", s, " ", s, " ", s, " ", s); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_StringPrintf)->Range(0, 1024); |
| |
| // Benchmark using absl::Substitute() together with SimpleItoa() to print |
| // numbers. This demonstrates that absl::Substitute() is faster than |
| // StringPrintf() even when the inputs are numbers. |
| void BM_SubstituteNumber(benchmark::State& state) { |
| const int n = state.range(0); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = |
| absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", n, n + 1, n + 2, |
| n + 3, n + 4, n + 5, n + 6, n + 7, n + 8, n + 9); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_SubstituteNumber)->Arg(0)->Arg(1 << 20); |
| |
| // For comparison with BM_SubstituteNumber. |
| void BM_StrCatNumber(benchmark::State& state) { |
| const int n = state.range(0); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = |
| absl::StrCat(n, " ", n + 1, " ", n + 2, " ", n + 3, " ", n + 4, " ", |
| n + 5, " ", n + 6, " ", n + 7, " ", n + 8, " ", n + 9); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_StrCatNumber)->Arg(0)->Arg(1 << 20); |
| |
| // Benchmark using absl::Substitute() with a single substitution, to test the |
| // speed at which it copies simple text. Even in this case, it's faster |
| // that StringPrintf(). |
| void BM_SubstituteSimpleText(benchmark::State& state) { |
| std::string s(state.range(0), 'x'); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = absl::Substitute("$0", s.c_str()); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_SubstituteSimpleText)->Range(0, 1024); |
| |
| // For comparison with BM_SubstituteSimpleText. |
| void BM_StrCatSimpleText(benchmark::State& state) { |
| std::string s(state.range(0), 'x'); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = absl::StrCat("", s); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_StrCatSimpleText)->Range(0, 1024); |
| |
| std::string MakeFormatByDensity(int density, bool subs_mode) { |
| std::string format((2 + density) * 10, 'x'); |
| for (size_t i = 0; i < 10; ++i) { |
| format[density * i] = subs_mode ? '$' : '%'; |
| format[density * i + 1] = subs_mode ? ('0' + i) : 's'; |
| } |
| return format; |
| } |
| |
| void BM_SubstituteDensity(benchmark::State& state) { |
| const std::string s(10, 'x'); |
| const std::string format = MakeFormatByDensity(state.range(0), true); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = absl::Substitute(format, s, s, s, s, s, s, s, s, s, s); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_SubstituteDensity)->Range(0, 256); |
| |
| void BM_StrCatDensity(benchmark::State& state) { |
| const std::string s(10, 'x'); |
| const std::string format(state.range(0), 'x'); |
| int64_t bytes = 0; |
| for (auto _ : state) { |
| std::string result = |
| absl::StrCat(s, format, s, format, s, format, s, format, s, format, s, |
| format, s, format, s, format, s, format, s, format); |
| bytes += result.size(); |
| } |
| state.SetBytesProcessed(bytes); |
| } |
| BENCHMARK(BM_StrCatDensity)->Range(0, 256); |
| |
| } // namespace |