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