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_ToInt64Nanoseconds(benchmark::State & state)293 void BM_Duration_ToInt64Nanoseconds(benchmark::State& state) {
294 absl::Duration d = absl::Seconds(100000);
295 while (state.KeepRunning()) {
296 benchmark::DoNotOptimize(absl::ToInt64Nanoseconds(d));
297 }
298 }
299 BENCHMARK(BM_Duration_ToInt64Nanoseconds);
300
BM_Duration_ToInt64Microseconds(benchmark::State & state)301 void BM_Duration_ToInt64Microseconds(benchmark::State& state) {
302 absl::Duration d = absl::Seconds(100000);
303 while (state.KeepRunning()) {
304 benchmark::DoNotOptimize(absl::ToInt64Microseconds(d));
305 }
306 }
307 BENCHMARK(BM_Duration_ToInt64Microseconds);
308
BM_Duration_ToInt64Milliseconds(benchmark::State & state)309 void BM_Duration_ToInt64Milliseconds(benchmark::State& state) {
310 absl::Duration d = absl::Seconds(100000);
311 while (state.KeepRunning()) {
312 benchmark::DoNotOptimize(absl::ToInt64Milliseconds(d));
313 }
314 }
315 BENCHMARK(BM_Duration_ToInt64Milliseconds);
316
BM_Duration_ToInt64Seconds(benchmark::State & state)317 void BM_Duration_ToInt64Seconds(benchmark::State& state) {
318 absl::Duration d = absl::Seconds(100000);
319 while (state.KeepRunning()) {
320 benchmark::DoNotOptimize(absl::ToInt64Seconds(d));
321 }
322 }
323 BENCHMARK(BM_Duration_ToInt64Seconds);
324
BM_Duration_ToInt64Minutes(benchmark::State & state)325 void BM_Duration_ToInt64Minutes(benchmark::State& state) {
326 absl::Duration d = absl::Seconds(100000);
327 while (state.KeepRunning()) {
328 benchmark::DoNotOptimize(absl::ToInt64Minutes(d));
329 }
330 }
331 BENCHMARK(BM_Duration_ToInt64Minutes);
332
BM_Duration_ToInt64Hours(benchmark::State & state)333 void BM_Duration_ToInt64Hours(benchmark::State& state) {
334 absl::Duration d = absl::Seconds(100000);
335 while (state.KeepRunning()) {
336 benchmark::DoNotOptimize(absl::ToInt64Hours(d));
337 }
338 }
339 BENCHMARK(BM_Duration_ToInt64Hours);
340
341 //
342 // To/FromTimespec
343 //
344
BM_Duration_ToTimespec_AbslTime(benchmark::State & state)345 void BM_Duration_ToTimespec_AbslTime(benchmark::State& state) {
346 absl::Duration d = absl::Seconds(1);
347 while (state.KeepRunning()) {
348 benchmark::DoNotOptimize(absl::ToTimespec(d));
349 }
350 }
351 BENCHMARK(BM_Duration_ToTimespec_AbslTime);
352
DoubleToTimespec(double seconds)353 ABSL_ATTRIBUTE_NOINLINE timespec DoubleToTimespec(double seconds) {
354 timespec ts;
355 ts.tv_sec = seconds;
356 ts.tv_nsec = (seconds - ts.tv_sec) * (1000 * 1000 * 1000);
357 return ts;
358 }
359
BM_Duration_ToTimespec_Double(benchmark::State & state)360 void BM_Duration_ToTimespec_Double(benchmark::State& state) {
361 while (state.KeepRunning()) {
362 benchmark::DoNotOptimize(DoubleToTimespec(1.0));
363 }
364 }
365 BENCHMARK(BM_Duration_ToTimespec_Double);
366
BM_Duration_FromTimespec_AbslTime(benchmark::State & state)367 void BM_Duration_FromTimespec_AbslTime(benchmark::State& state) {
368 timespec ts;
369 ts.tv_sec = 0;
370 ts.tv_nsec = 0;
371 while (state.KeepRunning()) {
372 if (++ts.tv_nsec == 1000 * 1000 * 1000) {
373 ++ts.tv_sec;
374 ts.tv_nsec = 0;
375 }
376 benchmark::DoNotOptimize(absl::DurationFromTimespec(ts));
377 }
378 }
379 BENCHMARK(BM_Duration_FromTimespec_AbslTime);
380
TimespecToDouble(timespec ts)381 ABSL_ATTRIBUTE_NOINLINE double TimespecToDouble(timespec ts) {
382 return ts.tv_sec + (ts.tv_nsec / (1000 * 1000 * 1000));
383 }
384
BM_Duration_FromTimespec_Double(benchmark::State & state)385 void BM_Duration_FromTimespec_Double(benchmark::State& state) {
386 timespec ts;
387 ts.tv_sec = 0;
388 ts.tv_nsec = 0;
389 while (state.KeepRunning()) {
390 if (++ts.tv_nsec == 1000 * 1000 * 1000) {
391 ++ts.tv_sec;
392 ts.tv_nsec = 0;
393 }
394 benchmark::DoNotOptimize(TimespecToDouble(ts));
395 }
396 }
397 BENCHMARK(BM_Duration_FromTimespec_Double);
398
399 //
400 // String conversions
401 //
402
403 const char* const kDurations[] = {
404 "0", // 0
405 "123ns", // 1
406 "1h2m3s", // 2
407 "-2h3m4.005006007s", // 3
408 "2562047788015215h30m7.99999999975s", // 4
409 };
410 const int kNumDurations = sizeof(kDurations) / sizeof(kDurations[0]);
411
BM_Duration_FormatDuration(benchmark::State & state)412 void BM_Duration_FormatDuration(benchmark::State& state) {
413 const std::string s = kDurations[state.range(0)];
414 state.SetLabel(s);
415 absl::Duration d;
416 absl::ParseDuration(kDurations[state.range(0)], &d);
417 while (state.KeepRunning()) {
418 benchmark::DoNotOptimize(absl::FormatDuration(d));
419 }
420 }
421 BENCHMARK(BM_Duration_FormatDuration)->DenseRange(0, kNumDurations - 1);
422
BM_Duration_ParseDuration(benchmark::State & state)423 void BM_Duration_ParseDuration(benchmark::State& state) {
424 const std::string s = kDurations[state.range(0)];
425 state.SetLabel(s);
426 absl::Duration d;
427 while (state.KeepRunning()) {
428 benchmark::DoNotOptimize(absl::ParseDuration(s, &d));
429 }
430 }
431 BENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1);
432
433 //
434 // Flag access
435 //
BM_Duration_GetFlag(benchmark::State & state)436 void BM_Duration_GetFlag(benchmark::State& state) {
437 while (state.KeepRunning()) {
438 benchmark::DoNotOptimize(
439 absl::GetFlag(FLAGS_absl_duration_flag_for_benchmark));
440 }
441 }
442 BENCHMARK(BM_Duration_GetFlag);
443
444 } // namespace
445