duration_benchmark.cc (12783B)
1 // Copyright 2018 The Abseil Authors. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // https://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 #include <cmath> 15 #include <cstddef> 16 #include <cstdint> 17 #include <ctime> 18 #include <string> 19 20 #include "absl/base/attributes.h" 21 #include "absl/flags/flag.h" 22 #include "absl/time/time.h" 23 #include "benchmark/benchmark.h" 24 25 ABSL_FLAG(absl::Duration, absl_duration_flag_for_benchmark, 26 absl::Milliseconds(1), 27 "Flag to use for benchmarking duration flag access speed."); 28 29 namespace { 30 31 // 32 // Factory functions 33 // 34 35 void BM_Duration_Factory_Nanoseconds(benchmark::State& state) { 36 int64_t i = 0; 37 while (state.KeepRunning()) { 38 benchmark::DoNotOptimize(absl::Nanoseconds(i)); 39 i += 314159; 40 } 41 } 42 BENCHMARK(BM_Duration_Factory_Nanoseconds); 43 44 void BM_Duration_Factory_Microseconds(benchmark::State& state) { 45 int64_t i = 0; 46 while (state.KeepRunning()) { 47 benchmark::DoNotOptimize(absl::Microseconds(i)); 48 i += 314; 49 } 50 } 51 BENCHMARK(BM_Duration_Factory_Microseconds); 52 53 void BM_Duration_Factory_Milliseconds(benchmark::State& state) { 54 int64_t i = 0; 55 while (state.KeepRunning()) { 56 benchmark::DoNotOptimize(absl::Milliseconds(i)); 57 i += 1; 58 } 59 } 60 BENCHMARK(BM_Duration_Factory_Milliseconds); 61 62 void BM_Duration_Factory_Seconds(benchmark::State& state) { 63 int64_t i = 0; 64 while (state.KeepRunning()) { 65 benchmark::DoNotOptimize(absl::Seconds(i)); 66 i += 1; 67 } 68 } 69 BENCHMARK(BM_Duration_Factory_Seconds); 70 71 void BM_Duration_Factory_Minutes(benchmark::State& state) { 72 int64_t i = 0; 73 while (state.KeepRunning()) { 74 benchmark::DoNotOptimize(absl::Minutes(i)); 75 i += 1; 76 } 77 } 78 BENCHMARK(BM_Duration_Factory_Minutes); 79 80 void BM_Duration_Factory_Hours(benchmark::State& state) { 81 int64_t i = 0; 82 while (state.KeepRunning()) { 83 benchmark::DoNotOptimize(absl::Hours(i)); 84 i += 1; 85 } 86 } 87 BENCHMARK(BM_Duration_Factory_Hours); 88 89 void BM_Duration_Factory_DoubleNanoseconds(benchmark::State& state) { 90 double d = 1; 91 while (state.KeepRunning()) { 92 benchmark::DoNotOptimize(absl::Nanoseconds(d)); 93 d = d * 1.00000001 + 1; 94 } 95 } 96 BENCHMARK(BM_Duration_Factory_DoubleNanoseconds); 97 98 void BM_Duration_Factory_DoubleMicroseconds(benchmark::State& state) { 99 double d = 1e-3; 100 while (state.KeepRunning()) { 101 benchmark::DoNotOptimize(absl::Microseconds(d)); 102 d = d * 1.00000001 + 1e-3; 103 } 104 } 105 BENCHMARK(BM_Duration_Factory_DoubleMicroseconds); 106 107 void BM_Duration_Factory_DoubleMilliseconds(benchmark::State& state) { 108 double d = 1e-6; 109 while (state.KeepRunning()) { 110 benchmark::DoNotOptimize(absl::Milliseconds(d)); 111 d = d * 1.00000001 + 1e-6; 112 } 113 } 114 BENCHMARK(BM_Duration_Factory_DoubleMilliseconds); 115 116 void BM_Duration_Factory_DoubleSeconds(benchmark::State& state) { 117 double d = 1e-9; 118 while (state.KeepRunning()) { 119 benchmark::DoNotOptimize(absl::Seconds(d)); 120 d = d * 1.00000001 + 1e-9; 121 } 122 } 123 BENCHMARK(BM_Duration_Factory_DoubleSeconds); 124 125 void BM_Duration_Factory_DoubleMinutes(benchmark::State& state) { 126 double d = 1e-9; 127 while (state.KeepRunning()) { 128 benchmark::DoNotOptimize(absl::Minutes(d)); 129 d = d * 1.00000001 + 1e-9; 130 } 131 } 132 BENCHMARK(BM_Duration_Factory_DoubleMinutes); 133 134 void BM_Duration_Factory_DoubleHours(benchmark::State& state) { 135 double d = 1e-9; 136 while (state.KeepRunning()) { 137 benchmark::DoNotOptimize(absl::Hours(d)); 138 d = d * 1.00000001 + 1e-9; 139 } 140 } 141 BENCHMARK(BM_Duration_Factory_DoubleHours); 142 143 // 144 // Arithmetic 145 // 146 147 void BM_Duration_Addition(benchmark::State& state) { 148 absl::Duration d = absl::Nanoseconds(1); 149 absl::Duration step = absl::Milliseconds(1); 150 while (state.KeepRunning()) { 151 benchmark::DoNotOptimize(d += step); 152 } 153 } 154 BENCHMARK(BM_Duration_Addition); 155 156 void BM_Duration_Subtraction(benchmark::State& state) { 157 absl::Duration d = absl::Seconds(std::numeric_limits<int64_t>::max()); 158 absl::Duration step = absl::Milliseconds(1); 159 while (state.KeepRunning()) { 160 benchmark::DoNotOptimize(d -= step); 161 } 162 } 163 BENCHMARK(BM_Duration_Subtraction); 164 165 void BM_Duration_Multiplication_Fixed(benchmark::State& state) { 166 absl::Duration d = absl::Milliseconds(1); 167 absl::Duration s; 168 int i = 0; 169 while (state.KeepRunning()) { 170 benchmark::DoNotOptimize(s += d * (i + 1)); 171 ++i; 172 } 173 } 174 BENCHMARK(BM_Duration_Multiplication_Fixed); 175 176 void BM_Duration_Multiplication_Double(benchmark::State& state) { 177 absl::Duration d = absl::Milliseconds(1); 178 absl::Duration s; 179 int i = 0; 180 while (state.KeepRunning()) { 181 benchmark::DoNotOptimize(s += d * (i + 1.0)); 182 ++i; 183 } 184 } 185 BENCHMARK(BM_Duration_Multiplication_Double); 186 187 void BM_Duration_Division_Fixed(benchmark::State& state) { 188 absl::Duration d = absl::Seconds(1); 189 int i = 0; 190 while (state.KeepRunning()) { 191 benchmark::DoNotOptimize(d /= i + 1); 192 ++i; 193 } 194 } 195 BENCHMARK(BM_Duration_Division_Fixed); 196 197 void BM_Duration_Division_Double(benchmark::State& state) { 198 absl::Duration d = absl::Seconds(1); 199 int i = 0; 200 while (state.KeepRunning()) { 201 benchmark::DoNotOptimize(d /= i + 1.0); 202 ++i; 203 } 204 } 205 BENCHMARK(BM_Duration_Division_Double); 206 207 void BM_Duration_FDivDuration_Nanoseconds(benchmark::State& state) { 208 double d = 1; 209 int i = 0; 210 while (state.KeepRunning()) { 211 benchmark::DoNotOptimize( 212 d += absl::FDivDuration(absl::Milliseconds(i), absl::Nanoseconds(1))); 213 ++i; 214 } 215 } 216 BENCHMARK(BM_Duration_FDivDuration_Nanoseconds); 217 218 void BM_Duration_IDivDuration_Nanoseconds(benchmark::State& state) { 219 int64_t a = 1; 220 absl::Duration ignore; 221 int i = 0; 222 while (state.KeepRunning()) { 223 benchmark::DoNotOptimize(a += 224 absl::IDivDuration(absl::Nanoseconds(i), 225 absl::Nanoseconds(1), &ignore)); 226 ++i; 227 } 228 } 229 BENCHMARK(BM_Duration_IDivDuration_Nanoseconds); 230 231 void BM_Duration_IDivDuration_Microseconds(benchmark::State& state) { 232 int64_t a = 1; 233 absl::Duration ignore; 234 int i = 0; 235 while (state.KeepRunning()) { 236 benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Microseconds(i), 237 absl::Microseconds(1), 238 &ignore)); 239 ++i; 240 } 241 } 242 BENCHMARK(BM_Duration_IDivDuration_Microseconds); 243 244 void BM_Duration_IDivDuration_Milliseconds(benchmark::State& state) { 245 int64_t a = 1; 246 absl::Duration ignore; 247 int i = 0; 248 while (state.KeepRunning()) { 249 benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Milliseconds(i), 250 absl::Milliseconds(1), 251 &ignore)); 252 ++i; 253 } 254 } 255 BENCHMARK(BM_Duration_IDivDuration_Milliseconds); 256 257 void BM_Duration_IDivDuration_Seconds(benchmark::State& state) { 258 int64_t a = 1; 259 absl::Duration ignore; 260 int i = 0; 261 while (state.KeepRunning()) { 262 benchmark::DoNotOptimize( 263 a += absl::IDivDuration(absl::Seconds(i), absl::Seconds(1), &ignore)); 264 ++i; 265 } 266 } 267 BENCHMARK(BM_Duration_IDivDuration_Seconds); 268 269 void BM_Duration_IDivDuration_Minutes(benchmark::State& state) { 270 int64_t a = 1; 271 absl::Duration ignore; 272 int i = 0; 273 while (state.KeepRunning()) { 274 benchmark::DoNotOptimize( 275 a += absl::IDivDuration(absl::Minutes(i), absl::Minutes(1), &ignore)); 276 ++i; 277 } 278 } 279 BENCHMARK(BM_Duration_IDivDuration_Minutes); 280 281 void BM_Duration_IDivDuration_Hours(benchmark::State& state) { 282 int64_t a = 1; 283 absl::Duration ignore; 284 int i = 0; 285 while (state.KeepRunning()) { 286 benchmark::DoNotOptimize( 287 a += absl::IDivDuration(absl::Hours(i), absl::Hours(1), &ignore)); 288 ++i; 289 } 290 } 291 BENCHMARK(BM_Duration_IDivDuration_Hours); 292 293 void BM_Duration_Modulo(benchmark::State& state) { 294 int i = 0; 295 while (state.KeepRunning()) { 296 auto mod = absl::Seconds(i) % absl::Nanoseconds(12345); 297 benchmark::DoNotOptimize(mod); 298 ++i; 299 } 300 } 301 BENCHMARK(BM_Duration_Modulo); 302 303 void BM_Duration_Modulo_FastPath(benchmark::State& state) { 304 int i = 0; 305 while (state.KeepRunning()) { 306 auto mod = absl::Seconds(i) % absl::Milliseconds(1); 307 benchmark::DoNotOptimize(mod); 308 ++i; 309 } 310 } 311 BENCHMARK(BM_Duration_Modulo_FastPath); 312 313 void BM_Duration_ToInt64Nanoseconds(benchmark::State& state) { 314 absl::Duration d = absl::Seconds(100000); 315 while (state.KeepRunning()) { 316 benchmark::DoNotOptimize(absl::ToInt64Nanoseconds(d)); 317 } 318 } 319 BENCHMARK(BM_Duration_ToInt64Nanoseconds); 320 321 void BM_Duration_ToInt64Microseconds(benchmark::State& state) { 322 absl::Duration d = absl::Seconds(100000); 323 while (state.KeepRunning()) { 324 benchmark::DoNotOptimize(absl::ToInt64Microseconds(d)); 325 } 326 } 327 BENCHMARK(BM_Duration_ToInt64Microseconds); 328 329 void BM_Duration_ToInt64Milliseconds(benchmark::State& state) { 330 absl::Duration d = absl::Seconds(100000); 331 while (state.KeepRunning()) { 332 benchmark::DoNotOptimize(absl::ToInt64Milliseconds(d)); 333 } 334 } 335 BENCHMARK(BM_Duration_ToInt64Milliseconds); 336 337 void BM_Duration_ToInt64Seconds(benchmark::State& state) { 338 absl::Duration d = absl::Seconds(100000); 339 while (state.KeepRunning()) { 340 benchmark::DoNotOptimize(absl::ToInt64Seconds(d)); 341 } 342 } 343 BENCHMARK(BM_Duration_ToInt64Seconds); 344 345 void BM_Duration_ToInt64Minutes(benchmark::State& state) { 346 absl::Duration d = absl::Seconds(100000); 347 while (state.KeepRunning()) { 348 benchmark::DoNotOptimize(absl::ToInt64Minutes(d)); 349 } 350 } 351 BENCHMARK(BM_Duration_ToInt64Minutes); 352 353 void BM_Duration_ToInt64Hours(benchmark::State& state) { 354 absl::Duration d = absl::Seconds(100000); 355 while (state.KeepRunning()) { 356 benchmark::DoNotOptimize(absl::ToInt64Hours(d)); 357 } 358 } 359 BENCHMARK(BM_Duration_ToInt64Hours); 360 361 // 362 // To/FromTimespec 363 // 364 365 void BM_Duration_ToTimespec_AbslTime(benchmark::State& state) { 366 absl::Duration d = absl::Seconds(1); 367 while (state.KeepRunning()) { 368 benchmark::DoNotOptimize(absl::ToTimespec(d)); 369 } 370 } 371 BENCHMARK(BM_Duration_ToTimespec_AbslTime); 372 373 ABSL_ATTRIBUTE_NOINLINE timespec DoubleToTimespec(double seconds) { 374 timespec ts; 375 ts.tv_sec = seconds; 376 ts.tv_nsec = (seconds - ts.tv_sec) * (1000 * 1000 * 1000); 377 return ts; 378 } 379 380 void BM_Duration_ToTimespec_Double(benchmark::State& state) { 381 while (state.KeepRunning()) { 382 benchmark::DoNotOptimize(DoubleToTimespec(1.0)); 383 } 384 } 385 BENCHMARK(BM_Duration_ToTimespec_Double); 386 387 void BM_Duration_FromTimespec_AbslTime(benchmark::State& state) { 388 timespec ts; 389 ts.tv_sec = 0; 390 ts.tv_nsec = 0; 391 while (state.KeepRunning()) { 392 if (++ts.tv_nsec == 1000 * 1000 * 1000) { 393 ++ts.tv_sec; 394 ts.tv_nsec = 0; 395 } 396 benchmark::DoNotOptimize(absl::DurationFromTimespec(ts)); 397 } 398 } 399 BENCHMARK(BM_Duration_FromTimespec_AbslTime); 400 401 ABSL_ATTRIBUTE_NOINLINE double TimespecToDouble(timespec ts) { 402 return ts.tv_sec + (ts.tv_nsec / (1000 * 1000 * 1000)); 403 } 404 405 void BM_Duration_FromTimespec_Double(benchmark::State& state) { 406 timespec ts; 407 ts.tv_sec = 0; 408 ts.tv_nsec = 0; 409 while (state.KeepRunning()) { 410 if (++ts.tv_nsec == 1000 * 1000 * 1000) { 411 ++ts.tv_sec; 412 ts.tv_nsec = 0; 413 } 414 benchmark::DoNotOptimize(TimespecToDouble(ts)); 415 } 416 } 417 BENCHMARK(BM_Duration_FromTimespec_Double); 418 419 // 420 // String conversions 421 // 422 423 const char* const kDurations[] = { 424 "0", // 0 425 "123ns", // 1 426 "1h2m3s", // 2 427 "-2h3m4.005006007s", // 3 428 "2562047788015215h30m7.99999999975s", // 4 429 }; 430 const int kNumDurations = sizeof(kDurations) / sizeof(kDurations[0]); 431 432 void BM_Duration_FormatDuration(benchmark::State& state) { 433 const std::string s = kDurations[state.range(0)]; 434 state.SetLabel(s); 435 absl::Duration d; 436 absl::ParseDuration(kDurations[state.range(0)], &d); 437 while (state.KeepRunning()) { 438 benchmark::DoNotOptimize(absl::FormatDuration(d)); 439 } 440 } 441 BENCHMARK(BM_Duration_FormatDuration)->DenseRange(0, kNumDurations - 1); 442 443 void BM_Duration_ParseDuration(benchmark::State& state) { 444 const std::string s = kDurations[state.range(0)]; 445 state.SetLabel(s); 446 absl::Duration d; 447 while (state.KeepRunning()) { 448 benchmark::DoNotOptimize(absl::ParseDuration(s, &d)); 449 } 450 } 451 BENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1); 452 453 // 454 // Flag access 455 // 456 void BM_Duration_GetFlag(benchmark::State& state) { 457 while (state.KeepRunning()) { 458 benchmark::DoNotOptimize( 459 absl::GetFlag(FLAGS_absl_duration_flag_for_benchmark)); 460 } 461 } 462 BENCHMARK(BM_Duration_GetFlag); 463 464 } // namespace