charconv_benchmark.cc (7494B)
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 <cstdlib> 16 #include <cstring> 17 #include <string> 18 19 #include "absl/strings/charconv.h" 20 #include "benchmark/benchmark.h" 21 22 namespace { 23 24 void BM_Strtod_Pi(benchmark::State& state) { 25 const char* pi = "3.14159"; 26 for (auto s : state) { 27 benchmark::DoNotOptimize(pi); 28 benchmark::DoNotOptimize(strtod(pi, nullptr)); 29 } 30 } 31 BENCHMARK(BM_Strtod_Pi); 32 33 void BM_Absl_Pi(benchmark::State& state) { 34 const char* pi = "3.14159"; 35 const char* pi_end = pi + strlen(pi); 36 for (auto s : state) { 37 benchmark::DoNotOptimize(pi); 38 double v; 39 absl::from_chars(pi, pi_end, v); 40 benchmark::DoNotOptimize(v); 41 } 42 } 43 BENCHMARK(BM_Absl_Pi); 44 45 void BM_Strtod_Pi_float(benchmark::State& state) { 46 const char* pi = "3.14159"; 47 for (auto s : state) { 48 benchmark::DoNotOptimize(pi); 49 benchmark::DoNotOptimize(strtof(pi, nullptr)); 50 } 51 } 52 BENCHMARK(BM_Strtod_Pi_float); 53 54 void BM_Absl_Pi_float(benchmark::State& state) { 55 const char* pi = "3.14159"; 56 const char* pi_end = pi + strlen(pi); 57 for (auto s : state) { 58 benchmark::DoNotOptimize(pi); 59 float v; 60 absl::from_chars(pi, pi_end, v); 61 benchmark::DoNotOptimize(v); 62 } 63 } 64 BENCHMARK(BM_Absl_Pi_float); 65 66 void BM_Strtod_HardLarge(benchmark::State& state) { 67 const char* num = "272104041512242479.e200"; 68 for (auto s : state) { 69 benchmark::DoNotOptimize(num); 70 benchmark::DoNotOptimize(strtod(num, nullptr)); 71 } 72 } 73 BENCHMARK(BM_Strtod_HardLarge); 74 75 void BM_Absl_HardLarge(benchmark::State& state) { 76 const char* numstr = "272104041512242479.e200"; 77 const char* numstr_end = numstr + strlen(numstr); 78 for (auto s : state) { 79 benchmark::DoNotOptimize(numstr); 80 double v; 81 absl::from_chars(numstr, numstr_end, v); 82 benchmark::DoNotOptimize(v); 83 } 84 } 85 BENCHMARK(BM_Absl_HardLarge); 86 87 void BM_Strtod_HardSmall(benchmark::State& state) { 88 const char* num = "94080055902682397.e-242"; 89 for (auto s : state) { 90 benchmark::DoNotOptimize(num); 91 benchmark::DoNotOptimize(strtod(num, nullptr)); 92 } 93 } 94 BENCHMARK(BM_Strtod_HardSmall); 95 96 void BM_Absl_HardSmall(benchmark::State& state) { 97 const char* numstr = "94080055902682397.e-242"; 98 const char* numstr_end = numstr + strlen(numstr); 99 for (auto s : state) { 100 benchmark::DoNotOptimize(numstr); 101 double v; 102 absl::from_chars(numstr, numstr_end, v); 103 benchmark::DoNotOptimize(v); 104 } 105 } 106 BENCHMARK(BM_Absl_HardSmall); 107 108 void BM_Strtod_HugeMantissa(benchmark::State& state) { 109 std::string huge(200, '3'); 110 const char* num = huge.c_str(); 111 for (auto s : state) { 112 benchmark::DoNotOptimize(num); 113 benchmark::DoNotOptimize(strtod(num, nullptr)); 114 } 115 } 116 BENCHMARK(BM_Strtod_HugeMantissa); 117 118 void BM_Absl_HugeMantissa(benchmark::State& state) { 119 std::string huge(200, '3'); 120 const char* num = huge.c_str(); 121 const char* num_end = num + 200; 122 for (auto s : state) { 123 benchmark::DoNotOptimize(num); 124 double v; 125 absl::from_chars(num, num_end, v); 126 benchmark::DoNotOptimize(v); 127 } 128 } 129 BENCHMARK(BM_Absl_HugeMantissa); 130 131 std::string MakeHardCase(int length) { 132 // The number 1.1521...e-297 is exactly halfway between 12345 * 2**-1000 and 133 // the next larger representable number. The digits of this number are in 134 // the string below. 135 const std::string digits = 136 "1." 137 "152113937042223790993097181572444900347587985074226836242307364987727724" 138 "831384300183638649152607195040591791364113930628852279348613864894524591" 139 "272746490313676832900762939595690019745859128071117417798540258114233761" 140 "012939937017879509401007964861774960297319002612457273148497158989073482" 141 "171377406078223015359818300988676687994537274548940612510414856761641652" 142 "513434981938564294004070500716200446656421722229202383105446378511678258" 143 "370570631774499359748259931676320916632111681001853983492795053244971606" 144 "922718923011680846577744433974087653954904214152517799883551075537146316" 145 "168973685866425605046988661997658648354773076621610279716804960009043764" 146 "038392994055171112475093876476783502487512538082706095923790634572014823" 147 "78877699375152587890625" + 148 std::string(5000, '0'); 149 // generate the hard cases on either side for the given length. 150 // Lengths between 3 and 1000 are reasonable. 151 return digits.substr(0, length) + "1e-297"; 152 } 153 154 void BM_Strtod_Big_And_Difficult(benchmark::State& state) { 155 std::string testcase = MakeHardCase(state.range(0)); 156 const char* begin = testcase.c_str(); 157 for (auto s : state) { 158 benchmark::DoNotOptimize(begin); 159 benchmark::DoNotOptimize(strtod(begin, nullptr)); 160 } 161 } 162 BENCHMARK(BM_Strtod_Big_And_Difficult)->Range(3, 5000); 163 164 void BM_Absl_Big_And_Difficult(benchmark::State& state) { 165 std::string testcase = MakeHardCase(state.range(0)); 166 const char* begin = testcase.c_str(); 167 const char* end = begin + testcase.size(); 168 for (auto s : state) { 169 benchmark::DoNotOptimize(begin); 170 double v; 171 absl::from_chars(begin, end, v); 172 benchmark::DoNotOptimize(v); 173 } 174 } 175 BENCHMARK(BM_Absl_Big_And_Difficult)->Range(3, 5000); 176 177 } // namespace 178 179 // ------------------------------------------------------------------------ 180 // Benchmark Time CPU Iterations 181 // ------------------------------------------------------------------------ 182 // BM_Strtod_Pi 96 ns 96 ns 6337454 183 // BM_Absl_Pi 35 ns 35 ns 20031996 184 // BM_Strtod_Pi_float 91 ns 91 ns 7745851 185 // BM_Absl_Pi_float 35 ns 35 ns 20430298 186 // BM_Strtod_HardLarge 133 ns 133 ns 5288341 187 // BM_Absl_HardLarge 181 ns 181 ns 3855615 188 // BM_Strtod_HardSmall 279 ns 279 ns 2517243 189 // BM_Absl_HardSmall 287 ns 287 ns 2458744 190 // BM_Strtod_HugeMantissa 433 ns 433 ns 1604293 191 // BM_Absl_HugeMantissa 160 ns 160 ns 4403671 192 // BM_Strtod_Big_And_Difficult/3 236 ns 236 ns 2942496 193 // BM_Strtod_Big_And_Difficult/8 232 ns 232 ns 2983796 194 // BM_Strtod_Big_And_Difficult/64 437 ns 437 ns 1591951 195 // BM_Strtod_Big_And_Difficult/512 1738 ns 1738 ns 402519 196 // BM_Strtod_Big_And_Difficult/4096 3943 ns 3943 ns 176128 197 // BM_Strtod_Big_And_Difficult/5000 4397 ns 4397 ns 157878 198 // BM_Absl_Big_And_Difficult/3 39 ns 39 ns 17799583 199 // BM_Absl_Big_And_Difficult/8 43 ns 43 ns 16096859 200 // BM_Absl_Big_And_Difficult/64 550 ns 550 ns 1259717 201 // BM_Absl_Big_And_Difficult/512 4167 ns 4167 ns 171414 202 // BM_Absl_Big_And_Difficult/4096 9160 ns 9159 ns 76297 203 // BM_Absl_Big_And_Difficult/5000 9738 ns 9738 ns 70140