1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_split.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include <cstddef>
18*9356374aSAndroid Build Coastguard Worker #include <iterator>
19*9356374aSAndroid Build Coastguard Worker #include <string>
20*9356374aSAndroid Build Coastguard Worker #include <unordered_map>
21*9356374aSAndroid Build Coastguard Worker #include <unordered_set>
22*9356374aSAndroid Build Coastguard Worker #include <vector>
23*9356374aSAndroid Build Coastguard Worker
24*9356374aSAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
25*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/raw_logging.h"
26*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
27*9356374aSAndroid Build Coastguard Worker
28*9356374aSAndroid Build Coastguard Worker namespace {
29*9356374aSAndroid Build Coastguard Worker
MakeTestString(int desired_length)30*9356374aSAndroid Build Coastguard Worker std::string MakeTestString(int desired_length) {
31*9356374aSAndroid Build Coastguard Worker static const int kAverageValueLen = 25;
32*9356374aSAndroid Build Coastguard Worker std::string test(desired_length * kAverageValueLen, 'x');
33*9356374aSAndroid Build Coastguard Worker for (int i = 1; i < test.size(); i += kAverageValueLen) {
34*9356374aSAndroid Build Coastguard Worker test[i] = ';';
35*9356374aSAndroid Build Coastguard Worker }
36*9356374aSAndroid Build Coastguard Worker return test;
37*9356374aSAndroid Build Coastguard Worker }
38*9356374aSAndroid Build Coastguard Worker
BM_Split2StringView(benchmark::State & state)39*9356374aSAndroid Build Coastguard Worker void BM_Split2StringView(benchmark::State& state) {
40*9356374aSAndroid Build Coastguard Worker std::string test = MakeTestString(state.range(0));
41*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
42*9356374aSAndroid Build Coastguard Worker std::vector<absl::string_view> result = absl::StrSplit(test, ';');
43*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
44*9356374aSAndroid Build Coastguard Worker }
45*9356374aSAndroid Build Coastguard Worker }
46*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20);
47*9356374aSAndroid Build Coastguard Worker
48*9356374aSAndroid Build Coastguard Worker static const absl::string_view kDelimiters = ";:,.";
49*9356374aSAndroid Build Coastguard Worker
MakeMultiDelimiterTestString(int desired_length)50*9356374aSAndroid Build Coastguard Worker std::string MakeMultiDelimiterTestString(int desired_length) {
51*9356374aSAndroid Build Coastguard Worker static const int kAverageValueLen = 25;
52*9356374aSAndroid Build Coastguard Worker std::string test(desired_length * kAverageValueLen, 'x');
53*9356374aSAndroid Build Coastguard Worker for (int i = 0; i * kAverageValueLen < test.size(); ++i) {
54*9356374aSAndroid Build Coastguard Worker // Cycle through a variety of delimiters.
55*9356374aSAndroid Build Coastguard Worker test[i * kAverageValueLen] = kDelimiters[i % kDelimiters.size()];
56*9356374aSAndroid Build Coastguard Worker }
57*9356374aSAndroid Build Coastguard Worker return test;
58*9356374aSAndroid Build Coastguard Worker }
59*9356374aSAndroid Build Coastguard Worker
60*9356374aSAndroid Build Coastguard Worker // Measure StrSplit with ByAnyChar with four delimiters to choose from.
BM_Split2StringViewByAnyChar(benchmark::State & state)61*9356374aSAndroid Build Coastguard Worker void BM_Split2StringViewByAnyChar(benchmark::State& state) {
62*9356374aSAndroid Build Coastguard Worker std::string test = MakeMultiDelimiterTestString(state.range(0));
63*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
64*9356374aSAndroid Build Coastguard Worker std::vector<absl::string_view> result =
65*9356374aSAndroid Build Coastguard Worker absl::StrSplit(test, absl::ByAnyChar(kDelimiters));
66*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
67*9356374aSAndroid Build Coastguard Worker }
68*9356374aSAndroid Build Coastguard Worker }
69*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_Split2StringViewByAnyChar, 0, 1 << 20);
70*9356374aSAndroid Build Coastguard Worker
BM_Split2StringViewLifted(benchmark::State & state)71*9356374aSAndroid Build Coastguard Worker void BM_Split2StringViewLifted(benchmark::State& state) {
72*9356374aSAndroid Build Coastguard Worker std::string test = MakeTestString(state.range(0));
73*9356374aSAndroid Build Coastguard Worker std::vector<absl::string_view> result;
74*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
75*9356374aSAndroid Build Coastguard Worker result = absl::StrSplit(test, ';');
76*9356374aSAndroid Build Coastguard Worker }
77*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
78*9356374aSAndroid Build Coastguard Worker }
79*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_Split2StringViewLifted, 0, 1 << 20);
80*9356374aSAndroid Build Coastguard Worker
BM_Split2String(benchmark::State & state)81*9356374aSAndroid Build Coastguard Worker void BM_Split2String(benchmark::State& state) {
82*9356374aSAndroid Build Coastguard Worker std::string test = MakeTestString(state.range(0));
83*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
84*9356374aSAndroid Build Coastguard Worker std::vector<std::string> result = absl::StrSplit(test, ';');
85*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
86*9356374aSAndroid Build Coastguard Worker }
87*9356374aSAndroid Build Coastguard Worker }
88*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_Split2String, 0, 1 << 20);
89*9356374aSAndroid Build Coastguard Worker
90*9356374aSAndroid Build Coastguard Worker // This benchmark is for comparing Split2 to Split1 (SplitStringUsing). In
91*9356374aSAndroid Build Coastguard Worker // particular, this benchmark uses SkipEmpty() to match SplitStringUsing's
92*9356374aSAndroid Build Coastguard Worker // behavior.
BM_Split2SplitStringUsing(benchmark::State & state)93*9356374aSAndroid Build Coastguard Worker void BM_Split2SplitStringUsing(benchmark::State& state) {
94*9356374aSAndroid Build Coastguard Worker std::string test = MakeTestString(state.range(0));
95*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
96*9356374aSAndroid Build Coastguard Worker std::vector<std::string> result =
97*9356374aSAndroid Build Coastguard Worker absl::StrSplit(test, ';', absl::SkipEmpty());
98*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
99*9356374aSAndroid Build Coastguard Worker }
100*9356374aSAndroid Build Coastguard Worker }
101*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_Split2SplitStringUsing, 0, 1 << 20);
102*9356374aSAndroid Build Coastguard Worker
BM_SplitStringToUnorderedSet(benchmark::State & state)103*9356374aSAndroid Build Coastguard Worker void BM_SplitStringToUnorderedSet(benchmark::State& state) {
104*9356374aSAndroid Build Coastguard Worker const int len = state.range(0);
105*9356374aSAndroid Build Coastguard Worker std::string test(len, 'x');
106*9356374aSAndroid Build Coastguard Worker for (int i = 1; i < len; i += 2) {
107*9356374aSAndroid Build Coastguard Worker test[i] = ';';
108*9356374aSAndroid Build Coastguard Worker }
109*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
110*9356374aSAndroid Build Coastguard Worker std::unordered_set<std::string> result =
111*9356374aSAndroid Build Coastguard Worker absl::StrSplit(test, ':', absl::SkipEmpty());
112*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
113*9356374aSAndroid Build Coastguard Worker }
114*9356374aSAndroid Build Coastguard Worker }
115*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_SplitStringToUnorderedSet, 0, 1 << 20);
116*9356374aSAndroid Build Coastguard Worker
BM_SplitStringToUnorderedMap(benchmark::State & state)117*9356374aSAndroid Build Coastguard Worker void BM_SplitStringToUnorderedMap(benchmark::State& state) {
118*9356374aSAndroid Build Coastguard Worker const int len = state.range(0);
119*9356374aSAndroid Build Coastguard Worker std::string test(len, 'x');
120*9356374aSAndroid Build Coastguard Worker for (int i = 1; i < len; i += 2) {
121*9356374aSAndroid Build Coastguard Worker test[i] = ';';
122*9356374aSAndroid Build Coastguard Worker }
123*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
124*9356374aSAndroid Build Coastguard Worker std::unordered_map<std::string, std::string> result =
125*9356374aSAndroid Build Coastguard Worker absl::StrSplit(test, ':', absl::SkipEmpty());
126*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
127*9356374aSAndroid Build Coastguard Worker }
128*9356374aSAndroid Build Coastguard Worker }
129*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_SplitStringToUnorderedMap, 0, 1 << 20);
130*9356374aSAndroid Build Coastguard Worker
BM_SplitStringAllowEmpty(benchmark::State & state)131*9356374aSAndroid Build Coastguard Worker void BM_SplitStringAllowEmpty(benchmark::State& state) {
132*9356374aSAndroid Build Coastguard Worker const int len = state.range(0);
133*9356374aSAndroid Build Coastguard Worker std::string test(len, 'x');
134*9356374aSAndroid Build Coastguard Worker for (int i = 1; i < len; i += 2) {
135*9356374aSAndroid Build Coastguard Worker test[i] = ';';
136*9356374aSAndroid Build Coastguard Worker }
137*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
138*9356374aSAndroid Build Coastguard Worker std::vector<std::string> result = absl::StrSplit(test, ';');
139*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(result);
140*9356374aSAndroid Build Coastguard Worker }
141*9356374aSAndroid Build Coastguard Worker }
142*9356374aSAndroid Build Coastguard Worker BENCHMARK_RANGE(BM_SplitStringAllowEmpty, 0, 1 << 20);
143*9356374aSAndroid Build Coastguard Worker
144*9356374aSAndroid Build Coastguard Worker struct OneCharLiteral {
operator ()__anon089010420111::OneCharLiteral145*9356374aSAndroid Build Coastguard Worker char operator()() const { return 'X'; }
146*9356374aSAndroid Build Coastguard Worker };
147*9356374aSAndroid Build Coastguard Worker
148*9356374aSAndroid Build Coastguard Worker struct OneCharStringLiteral {
operator ()__anon089010420111::OneCharStringLiteral149*9356374aSAndroid Build Coastguard Worker const char* operator()() const { return "X"; }
150*9356374aSAndroid Build Coastguard Worker };
151*9356374aSAndroid Build Coastguard Worker
152*9356374aSAndroid Build Coastguard Worker template <typename DelimiterFactory>
BM_SplitStringWithOneChar(benchmark::State & state)153*9356374aSAndroid Build Coastguard Worker void BM_SplitStringWithOneChar(benchmark::State& state) {
154*9356374aSAndroid Build Coastguard Worker const auto delimiter = DelimiterFactory()();
155*9356374aSAndroid Build Coastguard Worker std::vector<absl::string_view> pieces;
156*9356374aSAndroid Build Coastguard Worker size_t v = 0;
157*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
158*9356374aSAndroid Build Coastguard Worker pieces = absl::StrSplit("The quick brown fox jumps over the lazy dog",
159*9356374aSAndroid Build Coastguard Worker delimiter);
160*9356374aSAndroid Build Coastguard Worker v += pieces.size();
161*9356374aSAndroid Build Coastguard Worker }
162*9356374aSAndroid Build Coastguard Worker ABSL_RAW_CHECK(v == state.iterations(), "");
163*9356374aSAndroid Build Coastguard Worker }
164*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharLiteral);
165*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharStringLiteral);
166*9356374aSAndroid Build Coastguard Worker
167*9356374aSAndroid Build Coastguard Worker template <typename DelimiterFactory>
BM_SplitStringWithOneCharNoVector(benchmark::State & state)168*9356374aSAndroid Build Coastguard Worker void BM_SplitStringWithOneCharNoVector(benchmark::State& state) {
169*9356374aSAndroid Build Coastguard Worker const auto delimiter = DelimiterFactory()();
170*9356374aSAndroid Build Coastguard Worker size_t v = 0;
171*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
172*9356374aSAndroid Build Coastguard Worker auto splitter = absl::StrSplit(
173*9356374aSAndroid Build Coastguard Worker "The quick brown fox jumps over the lazy dog", delimiter);
174*9356374aSAndroid Build Coastguard Worker v += std::distance(splitter.begin(), splitter.end());
175*9356374aSAndroid Build Coastguard Worker }
176*9356374aSAndroid Build Coastguard Worker ABSL_RAW_CHECK(v == state.iterations(), "");
177*9356374aSAndroid Build Coastguard Worker }
178*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharLiteral);
179*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharStringLiteral);
180*9356374aSAndroid Build Coastguard Worker
181*9356374aSAndroid Build Coastguard Worker } // namespace
182