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 "absl/strings/ascii.h" 16 17 #include <cctype> 18 #include <string> 19 #include <array> 20 #include <random> 21 22 #include "benchmark/benchmark.h" 23 24 namespace { 25 MakeShuffledBytes()26 std::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 36 template <typename Function> AsciiBenchmark(benchmark::State & state,Function f)37 void 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 50 using StdAsciiFunction = int (*)(int); 51 template <StdAsciiFunction f> BM_Ascii(benchmark::State & state)52 void BM_Ascii(benchmark::State& state) { 53 AsciiBenchmark(state, f); 54 } 55 56 using AbslAsciiIsFunction = bool (*)(unsigned char); 57 template <AbslAsciiIsFunction f> BM_Ascii(benchmark::State & state)58 void BM_Ascii(benchmark::State& state) { 59 AsciiBenchmark(state, f); 60 } 61 62 using AbslAsciiToFunction = char (*)(unsigned char); 63 template <AbslAsciiToFunction f> BM_Ascii(benchmark::State & state)64 void BM_Ascii(benchmark::State& state) { 65 AsciiBenchmark(state, f); 66 } 67 Noop(unsigned char b)68 inline char Noop(unsigned char b) { return static_cast<char>(b); } 69 70 BENCHMARK_TEMPLATE(BM_Ascii, Noop); 71 BENCHMARK_TEMPLATE(BM_Ascii, std::isalpha); 72 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalpha); 73 BENCHMARK_TEMPLATE(BM_Ascii, std::isdigit); 74 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isdigit); 75 BENCHMARK_TEMPLATE(BM_Ascii, std::isalnum); 76 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalnum); 77 BENCHMARK_TEMPLATE(BM_Ascii, std::isspace); 78 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isspace); 79 BENCHMARK_TEMPLATE(BM_Ascii, std::ispunct); 80 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_ispunct); 81 BENCHMARK_TEMPLATE(BM_Ascii, std::isblank); 82 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isblank); 83 BENCHMARK_TEMPLATE(BM_Ascii, std::iscntrl); 84 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_iscntrl); 85 BENCHMARK_TEMPLATE(BM_Ascii, std::isxdigit); 86 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isxdigit); 87 BENCHMARK_TEMPLATE(BM_Ascii, std::isprint); 88 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isprint); 89 BENCHMARK_TEMPLATE(BM_Ascii, std::isgraph); 90 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isgraph); 91 BENCHMARK_TEMPLATE(BM_Ascii, std::isupper); 92 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isupper); 93 BENCHMARK_TEMPLATE(BM_Ascii, std::islower); 94 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_islower); 95 BENCHMARK_TEMPLATE(BM_Ascii, isascii); 96 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isascii); 97 BENCHMARK_TEMPLATE(BM_Ascii, std::tolower); 98 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_tolower); 99 BENCHMARK_TEMPLATE(BM_Ascii, std::toupper); 100 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_toupper); 101 BM_StrToLower(benchmark::State & state)102 static 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 } 109 BENCHMARK(BM_StrToLower)->Range(1, 1 << 20); 110 BM_StrToUpper(benchmark::State & state)111 static 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 } 118 BENCHMARK(BM_StrToUpper)->Range(1, 1 << 20); 119 120 } // namespace 121