From 6d21df714aa6a2ab2fc4029ca71dcff2daa03ca1 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 5 Jan 2024 11:13:25 -0800 Subject: Extend BM_StrAppendInt to use log-uniform random numbers instead of constants This follows Benford's law, which is likely also a much more accurate representation of real data than a constant. We also add benchmarks for different integer types. PiperOrigin-RevId: 596039508 Change-Id: I4862c7cfdbf5face18ae31cf0bd2fd54e47684b7 --- absl/strings/BUILD.bazel | 2 + absl/strings/str_cat_benchmark.cc | 78 ++++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 3a244b5b..9cae69d0 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -1125,6 +1125,8 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":strings", + "//absl/random", + "//absl/random:distributions", "@com_github_google_benchmark//:benchmark_main", "@com_google_googletest//:gtest", ], diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc index 36600268..0a851e7b 100644 --- a/absl/strings/str_cat_benchmark.cc +++ b/absl/strings/str_cat_benchmark.cc @@ -12,15 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "absl/strings/str_cat.h" - +#include #include #include #include #include #include +#include +#include #include "benchmark/benchmark.h" +#include "absl/random/log_uniform_int_distribution.h" +#include "absl/random/random.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" @@ -141,58 +145,63 @@ void BM_DoubleToString_By_SixDigits(benchmark::State& state) { } BENCHMARK(BM_DoubleToString_By_SixDigits); -template -void BM_StrAppendImpl(benchmark::State& state, size_t total_bytes, - Chunks... chunks) { +template +void BM_StrAppendImpl(benchmark::State& state, Table table, size_t total_bytes, + std::index_sequence) { for (auto s : state) { + const size_t table_size = table.size(); + size_t i = 0; std::string result; while (result.size() < total_bytes) { - absl::StrAppend(&result, chunks...); + absl::StrAppend(&result, std::get(table[i])...); benchmark::DoNotOptimize(result); + ++i; + i -= i >= table_size ? table_size : 0; } } } -void BM_StrAppend(benchmark::State& state) { +template +void BM_StrAppend(benchmark::State& state, Array&& table) { const size_t total_bytes = state.range(0); const int chunks_at_a_time = state.range(1); - const absl::string_view kChunk = "0123456789"; switch (chunks_at_a_time) { case 1: - return BM_StrAppendImpl(state, total_bytes, kChunk); + return BM_StrAppendImpl(state, std::forward(table), total_bytes, + std::make_index_sequence<1>()); case 2: - return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk); + return BM_StrAppendImpl(state, std::forward(table), total_bytes, + std::make_index_sequence<2>()); case 4: - return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk, - kChunk); + return BM_StrAppendImpl(state, std::forward(table), total_bytes, + std::make_index_sequence<4>()); case 8: - return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk, - kChunk, kChunk, kChunk, kChunk, kChunk); + return BM_StrAppendImpl(state, std::forward(table), total_bytes, + std::make_index_sequence<8>()); default: std::abort(); } } -void BM_StrAppendInt(benchmark::State& state) { - const size_t total_bytes = state.range(0); - const int chunks_at_a_time = state.range(1); - const size_t kChunk = 1234; +void BM_StrAppendStr(benchmark::State& state) { + using T = absl::string_view; + using Row = std::tuple; + constexpr absl::string_view kChunk = "0123456789"; + Row row = {kChunk, kChunk, kChunk, kChunk, kChunk, kChunk, kChunk, kChunk}; + return BM_StrAppend(state, std::array({row})); +} - switch (chunks_at_a_time) { - case 1: - return BM_StrAppendImpl(state, total_bytes, kChunk); - case 2: - return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk); - case 4: - return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk, - kChunk); - case 8: - return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk, - kChunk, kChunk, kChunk, kChunk, kChunk); - default: - std::abort(); +template +void BM_StrAppendInt(benchmark::State& state) { + absl::BitGen rng; + absl::log_uniform_int_distribution dist; + std::array, (1 << 7)> table; + for (size_t i = 0; i < table.size(); ++i) { + table[i] = {dist(rng), dist(rng), dist(rng), dist(rng), + dist(rng), dist(rng), dist(rng), dist(rng)}; } + return BM_StrAppend(state, table); } template @@ -207,8 +216,11 @@ void StrAppendConfig(B* benchmark) { } } -BENCHMARK(BM_StrAppend)->Apply(StrAppendConfig); -BENCHMARK(BM_StrAppendInt)->Apply(StrAppendConfig); +BENCHMARK(BM_StrAppendStr)->Apply(StrAppendConfig); +BENCHMARK(BM_StrAppendInt)->Apply(StrAppendConfig); +BENCHMARK(BM_StrAppendInt)->Apply(StrAppendConfig); +BENCHMARK(BM_StrAppendInt)->Apply(StrAppendConfig); +BENCHMARK(BM_StrAppendInt)->Apply(StrAppendConfig); template void BM_StrCatImpl(benchmark::State& state, -- cgit v1.2.3