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