str_split_benchmark.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. #include "absl/strings/str_split.h"
  15. #include <iterator>
  16. #include <string>
  17. #include <unordered_map>
  18. #include <unordered_set>
  19. #include <vector>
  20. #include "benchmark/benchmark.h"
  21. #include "absl/base/internal/raw_logging.h"
  22. #include "absl/strings/string_view.h"
  23. namespace {
  24. std::string MakeTestString(int desired_length) {
  25. static const int kAverageValueLen = 25;
  26. std::string test(desired_length * kAverageValueLen, 'x');
  27. for (int i = 1; i < test.size(); i += kAverageValueLen) {
  28. test[i] = ';';
  29. }
  30. return test;
  31. }
  32. void BM_Split2StringView(benchmark::State& state) {
  33. std::string test = MakeTestString(state.range(0));
  34. for (auto _ : state) {
  35. std::vector<absl::string_view> result = absl::StrSplit(test, ';');
  36. benchmark::DoNotOptimize(result);
  37. }
  38. }
  39. BENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20);
  40. static const absl::string_view kDelimiters = ";:,.";
  41. std::string MakeMultiDelimiterTestString(int desired_length) {
  42. static const int kAverageValueLen = 25;
  43. std::string test(desired_length * kAverageValueLen, 'x');
  44. for (int i = 0; i * kAverageValueLen < test.size(); ++i) {
  45. // Cycle through a variety of delimiters.
  46. test[i * kAverageValueLen] = kDelimiters[i % kDelimiters.size()];
  47. }
  48. return test;
  49. }
  50. // Measure StrSplit with ByAnyChar with four delimiters to choose from.
  51. void BM_Split2StringViewByAnyChar(benchmark::State& state) {
  52. std::string test = MakeMultiDelimiterTestString(state.range(0));
  53. for (auto _ : state) {
  54. std::vector<absl::string_view> result =
  55. absl::StrSplit(test, absl::ByAnyChar(kDelimiters));
  56. benchmark::DoNotOptimize(result);
  57. }
  58. }
  59. BENCHMARK_RANGE(BM_Split2StringViewByAnyChar, 0, 1 << 20);
  60. void BM_Split2StringViewLifted(benchmark::State& state) {
  61. std::string test = MakeTestString(state.range(0));
  62. std::vector<absl::string_view> result;
  63. for (auto _ : state) {
  64. result = absl::StrSplit(test, ';');
  65. }
  66. benchmark::DoNotOptimize(result);
  67. }
  68. BENCHMARK_RANGE(BM_Split2StringViewLifted, 0, 1 << 20);
  69. void BM_Split2String(benchmark::State& state) {
  70. std::string test = MakeTestString(state.range(0));
  71. for (auto _ : state) {
  72. std::vector<std::string> result = absl::StrSplit(test, ';');
  73. benchmark::DoNotOptimize(result);
  74. }
  75. }
  76. BENCHMARK_RANGE(BM_Split2String, 0, 1 << 20);
  77. // This benchmark is for comparing Split2 to Split1 (SplitStringUsing). In
  78. // particular, this benchmark uses SkipEmpty() to match SplitStringUsing's
  79. // behavior.
  80. void BM_Split2SplitStringUsing(benchmark::State& state) {
  81. std::string test = MakeTestString(state.range(0));
  82. for (auto _ : state) {
  83. std::vector<std::string> result =
  84. absl::StrSplit(test, ';', absl::SkipEmpty());
  85. benchmark::DoNotOptimize(result);
  86. }
  87. }
  88. BENCHMARK_RANGE(BM_Split2SplitStringUsing, 0, 1 << 20);
  89. void BM_SplitStringToUnorderedSet(benchmark::State& state) {
  90. const int len = state.range(0);
  91. std::string test(len, 'x');
  92. for (int i = 1; i < len; i += 2) {
  93. test[i] = ';';
  94. }
  95. for (auto _ : state) {
  96. std::unordered_set<std::string> result =
  97. absl::StrSplit(test, ':', absl::SkipEmpty());
  98. benchmark::DoNotOptimize(result);
  99. }
  100. }
  101. BENCHMARK_RANGE(BM_SplitStringToUnorderedSet, 0, 1 << 20);
  102. void BM_SplitStringToUnorderedMap(benchmark::State& state) {
  103. const int len = state.range(0);
  104. std::string test(len, 'x');
  105. for (int i = 1; i < len; i += 2) {
  106. test[i] = ';';
  107. }
  108. for (auto _ : state) {
  109. std::unordered_map<std::string, std::string> result =
  110. absl::StrSplit(test, ':', absl::SkipEmpty());
  111. benchmark::DoNotOptimize(result);
  112. }
  113. }
  114. BENCHMARK_RANGE(BM_SplitStringToUnorderedMap, 0, 1 << 20);
  115. void BM_SplitStringAllowEmpty(benchmark::State& state) {
  116. const int len = state.range(0);
  117. std::string test(len, 'x');
  118. for (int i = 1; i < len; i += 2) {
  119. test[i] = ';';
  120. }
  121. for (auto _ : state) {
  122. std::vector<std::string> result = absl::StrSplit(test, ';');
  123. benchmark::DoNotOptimize(result);
  124. }
  125. }
  126. BENCHMARK_RANGE(BM_SplitStringAllowEmpty, 0, 1 << 20);
  127. struct OneCharLiteral {
  128. char operator()() const { return 'X'; }
  129. };
  130. struct OneCharStringLiteral {
  131. const char* operator()() const { return "X"; }
  132. };
  133. template <typename DelimiterFactory>
  134. void BM_SplitStringWithOneChar(benchmark::State& state) {
  135. const auto delimiter = DelimiterFactory()();
  136. std::vector<absl::string_view> pieces;
  137. size_t v = 0;
  138. for (auto _ : state) {
  139. pieces = absl::StrSplit("The quick brown fox jumps over the lazy dog",
  140. delimiter);
  141. v += pieces.size();
  142. }
  143. ABSL_RAW_CHECK(v == state.iterations(), "");
  144. }
  145. BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharLiteral);
  146. BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharStringLiteral);
  147. template <typename DelimiterFactory>
  148. void BM_SplitStringWithOneCharNoVector(benchmark::State& state) {
  149. const auto delimiter = DelimiterFactory()();
  150. size_t v = 0;
  151. for (auto _ : state) {
  152. auto splitter = absl::StrSplit(
  153. "The quick brown fox jumps over the lazy dog", delimiter);
  154. v += std::distance(splitter.begin(), splitter.end());
  155. }
  156. ABSL_RAW_CHECK(v == state.iterations(), "");
  157. }
  158. BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharLiteral);
  159. BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharStringLiteral);
  160. } // namespace