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/ascii.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include <algorithm>
18*9356374aSAndroid Build Coastguard Worker #include <cctype>
19*9356374aSAndroid Build Coastguard Worker #include <cstddef>
20*9356374aSAndroid Build Coastguard Worker #include <string>
21*9356374aSAndroid Build Coastguard Worker #include <array>
22*9356374aSAndroid Build Coastguard Worker #include <random>
23*9356374aSAndroid Build Coastguard Worker
24*9356374aSAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
25*9356374aSAndroid Build Coastguard Worker
26*9356374aSAndroid Build Coastguard Worker namespace {
27*9356374aSAndroid Build Coastguard Worker
MakeShuffledBytes()28*9356374aSAndroid Build Coastguard Worker std::array<unsigned char, 256> MakeShuffledBytes() {
29*9356374aSAndroid Build Coastguard Worker std::array<unsigned char, 256> bytes;
30*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i);
31*9356374aSAndroid Build Coastguard Worker std::random_device rd;
32*9356374aSAndroid Build Coastguard Worker std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()});
33*9356374aSAndroid Build Coastguard Worker std::mt19937 g(seed);
34*9356374aSAndroid Build Coastguard Worker std::shuffle(bytes.begin(), bytes.end(), g);
35*9356374aSAndroid Build Coastguard Worker return bytes;
36*9356374aSAndroid Build Coastguard Worker }
37*9356374aSAndroid Build Coastguard Worker
38*9356374aSAndroid Build Coastguard Worker template <typename Function>
AsciiBenchmark(benchmark::State & state,Function f)39*9356374aSAndroid Build Coastguard Worker void AsciiBenchmark(benchmark::State& state, Function f) {
40*9356374aSAndroid Build Coastguard Worker std::array<unsigned char, 256> bytes = MakeShuffledBytes();
41*9356374aSAndroid Build Coastguard Worker size_t sum = 0;
42*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
43*9356374aSAndroid Build Coastguard Worker for (unsigned char b : bytes) sum += f(b) ? 1 : 0;
44*9356374aSAndroid Build Coastguard Worker }
45*9356374aSAndroid Build Coastguard Worker // Make a copy of `sum` before calling `DoNotOptimize` to make sure that `sum`
46*9356374aSAndroid Build Coastguard Worker // can be put in a CPU register and not degrade performance in the loop above.
47*9356374aSAndroid Build Coastguard Worker size_t sum2 = sum;
48*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(sum2);
49*9356374aSAndroid Build Coastguard Worker state.SetBytesProcessed(state.iterations() * bytes.size());
50*9356374aSAndroid Build Coastguard Worker }
51*9356374aSAndroid Build Coastguard Worker
52*9356374aSAndroid Build Coastguard Worker using StdAsciiFunction = int (*)(int);
53*9356374aSAndroid Build Coastguard Worker template <StdAsciiFunction f>
BM_Ascii(benchmark::State & state)54*9356374aSAndroid Build Coastguard Worker void BM_Ascii(benchmark::State& state) {
55*9356374aSAndroid Build Coastguard Worker AsciiBenchmark(state, f);
56*9356374aSAndroid Build Coastguard Worker }
57*9356374aSAndroid Build Coastguard Worker
58*9356374aSAndroid Build Coastguard Worker using AbslAsciiIsFunction = bool (*)(unsigned char);
59*9356374aSAndroid Build Coastguard Worker template <AbslAsciiIsFunction f>
BM_Ascii(benchmark::State & state)60*9356374aSAndroid Build Coastguard Worker void BM_Ascii(benchmark::State& state) {
61*9356374aSAndroid Build Coastguard Worker AsciiBenchmark(state, f);
62*9356374aSAndroid Build Coastguard Worker }
63*9356374aSAndroid Build Coastguard Worker
64*9356374aSAndroid Build Coastguard Worker using AbslAsciiToFunction = char (*)(unsigned char);
65*9356374aSAndroid Build Coastguard Worker template <AbslAsciiToFunction f>
BM_Ascii(benchmark::State & state)66*9356374aSAndroid Build Coastguard Worker void BM_Ascii(benchmark::State& state) {
67*9356374aSAndroid Build Coastguard Worker AsciiBenchmark(state, f);
68*9356374aSAndroid Build Coastguard Worker }
69*9356374aSAndroid Build Coastguard Worker
Noop(unsigned char b)70*9356374aSAndroid Build Coastguard Worker inline char Noop(unsigned char b) { return static_cast<char>(b); }
71*9356374aSAndroid Build Coastguard Worker
72*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, Noop);
73*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isalpha);
74*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalpha);
75*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isdigit);
76*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isdigit);
77*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isalnum);
78*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalnum);
79*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isspace);
80*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isspace);
81*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::ispunct);
82*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_ispunct);
83*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isblank);
84*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isblank);
85*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::iscntrl);
86*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_iscntrl);
87*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isxdigit);
88*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isxdigit);
89*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isprint);
90*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isprint);
91*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isgraph);
92*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isgraph);
93*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::isupper);
94*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isupper);
95*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::islower);
96*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_islower);
97*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, isascii);
98*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isascii);
99*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::tolower);
100*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_tolower);
101*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, std::toupper);
102*9356374aSAndroid Build Coastguard Worker BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_toupper);
103*9356374aSAndroid Build Coastguard Worker
BM_StrToLower(benchmark::State & state)104*9356374aSAndroid Build Coastguard Worker static void BM_StrToLower(benchmark::State& state) {
105*9356374aSAndroid Build Coastguard Worker const int size = state.range(0);
106*9356374aSAndroid Build Coastguard Worker std::string s(size, 'X');
107*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
108*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(s);
109*9356374aSAndroid Build Coastguard Worker std::string res = absl::AsciiStrToLower(s);
110*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(res);
111*9356374aSAndroid Build Coastguard Worker }
112*9356374aSAndroid Build Coastguard Worker }
113*9356374aSAndroid Build Coastguard Worker BENCHMARK(BM_StrToLower)
114*9356374aSAndroid Build Coastguard Worker ->DenseRange(0, 32)
115*9356374aSAndroid Build Coastguard Worker ->RangeMultiplier(2)
116*9356374aSAndroid Build Coastguard Worker ->Range(64, 1 << 26);
117*9356374aSAndroid Build Coastguard Worker
BM_StrToUpper(benchmark::State & state)118*9356374aSAndroid Build Coastguard Worker static void BM_StrToUpper(benchmark::State& state) {
119*9356374aSAndroid Build Coastguard Worker const int size = state.range(0);
120*9356374aSAndroid Build Coastguard Worker std::string s(size, 'x');
121*9356374aSAndroid Build Coastguard Worker for (auto _ : state) {
122*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(s);
123*9356374aSAndroid Build Coastguard Worker std::string res = absl::AsciiStrToUpper(s);
124*9356374aSAndroid Build Coastguard Worker benchmark::DoNotOptimize(res);
125*9356374aSAndroid Build Coastguard Worker }
126*9356374aSAndroid Build Coastguard Worker }
127*9356374aSAndroid Build Coastguard Worker BENCHMARK(BM_StrToUpper)
128*9356374aSAndroid Build Coastguard Worker ->DenseRange(0, 32)
129*9356374aSAndroid Build Coastguard Worker ->RangeMultiplier(2)
130*9356374aSAndroid Build Coastguard Worker ->Range(64, 1 << 26);
131*9356374aSAndroid Build Coastguard Worker
132*9356374aSAndroid Build Coastguard Worker } // namespace
133