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
BM_Duration_Factory_Nanoseconds(benchmark::State & state)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
BM_Duration_Factory_Microseconds(benchmark::State & state)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
BM_Duration_Factory_Milliseconds(benchmark::State & state)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
BM_Duration_Factory_Seconds(benchmark::State & state)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
BM_Duration_Factory_Minutes(benchmark::State & state)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
BM_Duration_Factory_Hours(benchmark::State & state)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
BM_Duration_Factory_DoubleNanoseconds(benchmark::State & state)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
BM_Duration_Factory_DoubleMicroseconds(benchmark::State & state)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
BM_Duration_Factory_DoubleMilliseconds(benchmark::State & state)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
BM_Duration_Factory_DoubleSeconds(benchmark::State & state)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
BM_Duration_Factory_DoubleMinutes(benchmark::State & state)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
BM_Duration_Factory_DoubleHours(benchmark::State & state)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
BM_Duration_Addition(benchmark::State & state)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
BM_Duration_Subtraction(benchmark::State & state)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
BM_Duration_Multiplication_Fixed(benchmark::State & state)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
BM_Duration_Multiplication_Double(benchmark::State & state)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
BM_Duration_Division_Fixed(benchmark::State & state)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
BM_Duration_Division_Double(benchmark::State & state)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
BM_Duration_FDivDuration_Nanoseconds(benchmark::State & state)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
BM_Duration_IDivDuration_Nanoseconds(benchmark::State & state)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
BM_Duration_IDivDuration_Microseconds(benchmark::State & state)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
BM_Duration_IDivDuration_Milliseconds(benchmark::State & state)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
BM_Duration_IDivDuration_Seconds(benchmark::State & state)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
BM_Duration_IDivDuration_Minutes(benchmark::State & state)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
BM_Duration_IDivDuration_Hours(benchmark::State & state)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
BM_Duration_Modulo(benchmark::State & state)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
BM_Duration_Modulo_FastPath(benchmark::State & state)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
BM_Duration_ToInt64Nanoseconds(benchmark::State & state)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
BM_Duration_ToInt64Microseconds(benchmark::State & state)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
BM_Duration_ToInt64Milliseconds(benchmark::State & state)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
BM_Duration_ToInt64Seconds(benchmark::State & state)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
BM_Duration_ToInt64Minutes(benchmark::State & state)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
BM_Duration_ToInt64Hours(benchmark::State & state)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
BM_Duration_ToTimespec_AbslTime(benchmark::State & state)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
DoubleToTimespec(double seconds)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
BM_Duration_ToTimespec_Double(benchmark::State & state)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
BM_Duration_FromTimespec_AbslTime(benchmark::State & state)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
TimespecToDouble(timespec ts)401 ABSL_ATTRIBUTE_NOINLINE double TimespecToDouble(timespec ts) {
402 return ts.tv_sec + (ts.tv_nsec / (1000 * 1000 * 1000));
403 }
404
BM_Duration_FromTimespec_Double(benchmark::State & state)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
BM_Duration_FormatDuration(benchmark::State & state)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
BM_Duration_ParseDuration(benchmark::State & state)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 //
BM_Duration_GetFlag(benchmark::State & state)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
465