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/time/time.h"
22 #include "benchmark/benchmark.h"
23
24 namespace {
25
26 //
27 // Factory functions
28 //
29
BM_Duration_Factory_Nanoseconds(benchmark::State & state)30 void BM_Duration_Factory_Nanoseconds(benchmark::State& state) {
31 int64_t i = 0;
32 while (state.KeepRunning()) {
33 benchmark::DoNotOptimize(absl::Nanoseconds(i));
34 i += 314159;
35 }
36 }
37 BENCHMARK(BM_Duration_Factory_Nanoseconds);
38
BM_Duration_Factory_Microseconds(benchmark::State & state)39 void BM_Duration_Factory_Microseconds(benchmark::State& state) {
40 int64_t i = 0;
41 while (state.KeepRunning()) {
42 benchmark::DoNotOptimize(absl::Microseconds(i));
43 i += 314;
44 }
45 }
46 BENCHMARK(BM_Duration_Factory_Microseconds);
47
BM_Duration_Factory_Milliseconds(benchmark::State & state)48 void BM_Duration_Factory_Milliseconds(benchmark::State& state) {
49 int64_t i = 0;
50 while (state.KeepRunning()) {
51 benchmark::DoNotOptimize(absl::Milliseconds(i));
52 i += 1;
53 }
54 }
55 BENCHMARK(BM_Duration_Factory_Milliseconds);
56
BM_Duration_Factory_Seconds(benchmark::State & state)57 void BM_Duration_Factory_Seconds(benchmark::State& state) {
58 int64_t i = 0;
59 while (state.KeepRunning()) {
60 benchmark::DoNotOptimize(absl::Seconds(i));
61 i += 1;
62 }
63 }
64 BENCHMARK(BM_Duration_Factory_Seconds);
65
BM_Duration_Factory_Minutes(benchmark::State & state)66 void BM_Duration_Factory_Minutes(benchmark::State& state) {
67 int64_t i = 0;
68 while (state.KeepRunning()) {
69 benchmark::DoNotOptimize(absl::Minutes(i));
70 i += 1;
71 }
72 }
73 BENCHMARK(BM_Duration_Factory_Minutes);
74
BM_Duration_Factory_Hours(benchmark::State & state)75 void BM_Duration_Factory_Hours(benchmark::State& state) {
76 int64_t i = 0;
77 while (state.KeepRunning()) {
78 benchmark::DoNotOptimize(absl::Hours(i));
79 i += 1;
80 }
81 }
82 BENCHMARK(BM_Duration_Factory_Hours);
83
BM_Duration_Factory_DoubleNanoseconds(benchmark::State & state)84 void BM_Duration_Factory_DoubleNanoseconds(benchmark::State& state) {
85 double d = 1;
86 while (state.KeepRunning()) {
87 benchmark::DoNotOptimize(absl::Nanoseconds(d));
88 d = d * 1.00000001 + 1;
89 }
90 }
91 BENCHMARK(BM_Duration_Factory_DoubleNanoseconds);
92
BM_Duration_Factory_DoubleMicroseconds(benchmark::State & state)93 void BM_Duration_Factory_DoubleMicroseconds(benchmark::State& state) {
94 double d = 1e-3;
95 while (state.KeepRunning()) {
96 benchmark::DoNotOptimize(absl::Microseconds(d));
97 d = d * 1.00000001 + 1e-3;
98 }
99 }
100 BENCHMARK(BM_Duration_Factory_DoubleMicroseconds);
101
BM_Duration_Factory_DoubleMilliseconds(benchmark::State & state)102 void BM_Duration_Factory_DoubleMilliseconds(benchmark::State& state) {
103 double d = 1e-6;
104 while (state.KeepRunning()) {
105 benchmark::DoNotOptimize(absl::Milliseconds(d));
106 d = d * 1.00000001 + 1e-6;
107 }
108 }
109 BENCHMARK(BM_Duration_Factory_DoubleMilliseconds);
110
BM_Duration_Factory_DoubleSeconds(benchmark::State & state)111 void BM_Duration_Factory_DoubleSeconds(benchmark::State& state) {
112 double d = 1e-9;
113 while (state.KeepRunning()) {
114 benchmark::DoNotOptimize(absl::Seconds(d));
115 d = d * 1.00000001 + 1e-9;
116 }
117 }
118 BENCHMARK(BM_Duration_Factory_DoubleSeconds);
119
BM_Duration_Factory_DoubleMinutes(benchmark::State & state)120 void BM_Duration_Factory_DoubleMinutes(benchmark::State& state) {
121 double d = 1e-9;
122 while (state.KeepRunning()) {
123 benchmark::DoNotOptimize(absl::Minutes(d));
124 d = d * 1.00000001 + 1e-9;
125 }
126 }
127 BENCHMARK(BM_Duration_Factory_DoubleMinutes);
128
BM_Duration_Factory_DoubleHours(benchmark::State & state)129 void BM_Duration_Factory_DoubleHours(benchmark::State& state) {
130 double d = 1e-9;
131 while (state.KeepRunning()) {
132 benchmark::DoNotOptimize(absl::Hours(d));
133 d = d * 1.00000001 + 1e-9;
134 }
135 }
136 BENCHMARK(BM_Duration_Factory_DoubleHours);
137
138 //
139 // Arithmetic
140 //
141
BM_Duration_Addition(benchmark::State & state)142 void BM_Duration_Addition(benchmark::State& state) {
143 absl::Duration d = absl::Nanoseconds(1);
144 absl::Duration step = absl::Milliseconds(1);
145 while (state.KeepRunning()) {
146 benchmark::DoNotOptimize(d += step);
147 }
148 }
149 BENCHMARK(BM_Duration_Addition);
150
BM_Duration_Subtraction(benchmark::State & state)151 void BM_Duration_Subtraction(benchmark::State& state) {
152 absl::Duration d = absl::Seconds(std::numeric_limits<int64_t>::max());
153 absl::Duration step = absl::Milliseconds(1);
154 while (state.KeepRunning()) {
155 benchmark::DoNotOptimize(d -= step);
156 }
157 }
158 BENCHMARK(BM_Duration_Subtraction);
159
BM_Duration_Multiplication_Fixed(benchmark::State & state)160 void BM_Duration_Multiplication_Fixed(benchmark::State& state) {
161 absl::Duration d = absl::Milliseconds(1);
162 absl::Duration s;
163 int i = 0;
164 while (state.KeepRunning()) {
165 benchmark::DoNotOptimize(s += d * (i + 1));
166 ++i;
167 }
168 }
169 BENCHMARK(BM_Duration_Multiplication_Fixed);
170
BM_Duration_Multiplication_Double(benchmark::State & state)171 void BM_Duration_Multiplication_Double(benchmark::State& state) {
172 absl::Duration d = absl::Milliseconds(1);
173 absl::Duration s;
174 int i = 0;
175 while (state.KeepRunning()) {
176 benchmark::DoNotOptimize(s += d * (i + 1.0));
177 ++i;
178 }
179 }
180 BENCHMARK(BM_Duration_Multiplication_Double);
181
BM_Duration_Division_Fixed(benchmark::State & state)182 void BM_Duration_Division_Fixed(benchmark::State& state) {
183 absl::Duration d = absl::Seconds(1);
184 int i = 0;
185 while (state.KeepRunning()) {
186 benchmark::DoNotOptimize(d /= i + 1);
187 ++i;
188 }
189 }
190 BENCHMARK(BM_Duration_Division_Fixed);
191
BM_Duration_Division_Double(benchmark::State & state)192 void BM_Duration_Division_Double(benchmark::State& state) {
193 absl::Duration d = absl::Seconds(1);
194 int i = 0;
195 while (state.KeepRunning()) {
196 benchmark::DoNotOptimize(d /= i + 1.0);
197 ++i;
198 }
199 }
200 BENCHMARK(BM_Duration_Division_Double);
201
BM_Duration_FDivDuration_Nanoseconds(benchmark::State & state)202 void BM_Duration_FDivDuration_Nanoseconds(benchmark::State& state) {
203 double d = 1;
204 int i = 0;
205 while (state.KeepRunning()) {
206 benchmark::DoNotOptimize(
207 d += absl::FDivDuration(absl::Milliseconds(i), absl::Nanoseconds(1)));
208 ++i;
209 }
210 }
211 BENCHMARK(BM_Duration_FDivDuration_Nanoseconds);
212
BM_Duration_IDivDuration_Nanoseconds(benchmark::State & state)213 void BM_Duration_IDivDuration_Nanoseconds(benchmark::State& state) {
214 int64_t a = 1;
215 absl::Duration ignore;
216 int i = 0;
217 while (state.KeepRunning()) {
218 benchmark::DoNotOptimize(a +=
219 absl::IDivDuration(absl::Nanoseconds(i),
220 absl::Nanoseconds(1), &ignore));
221 ++i;
222 }
223 }
224 BENCHMARK(BM_Duration_IDivDuration_Nanoseconds);
225
BM_Duration_IDivDuration_Microseconds(benchmark::State & state)226 void BM_Duration_IDivDuration_Microseconds(benchmark::State& state) {
227 int64_t a = 1;
228 absl::Duration ignore;
229 int i = 0;
230 while (state.KeepRunning()) {
231 benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Microseconds(i),
232 absl::Microseconds(1),
233 &ignore));
234 ++i;
235 }
236 }
237 BENCHMARK(BM_Duration_IDivDuration_Microseconds);
238
BM_Duration_IDivDuration_Milliseconds(benchmark::State & state)239 void BM_Duration_IDivDuration_Milliseconds(benchmark::State& state) {
240 int64_t a = 1;
241 absl::Duration ignore;
242 int i = 0;
243 while (state.KeepRunning()) {
244 benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Milliseconds(i),
245 absl::Milliseconds(1),
246 &ignore));
247 ++i;
248 }
249 }
250 BENCHMARK(BM_Duration_IDivDuration_Milliseconds);
251
BM_Duration_IDivDuration_Seconds(benchmark::State & state)252 void BM_Duration_IDivDuration_Seconds(benchmark::State& state) {
253 int64_t a = 1;
254 absl::Duration ignore;
255 int i = 0;
256 while (state.KeepRunning()) {
257 benchmark::DoNotOptimize(
258 a += absl::IDivDuration(absl::Seconds(i), absl::Seconds(1), &ignore));
259 ++i;
260 }
261 }
262 BENCHMARK(BM_Duration_IDivDuration_Seconds);
263
BM_Duration_IDivDuration_Minutes(benchmark::State & state)264 void BM_Duration_IDivDuration_Minutes(benchmark::State& state) {
265 int64_t a = 1;
266 absl::Duration ignore;
267 int i = 0;
268 while (state.KeepRunning()) {
269 benchmark::DoNotOptimize(
270 a += absl::IDivDuration(absl::Minutes(i), absl::Minutes(1), &ignore));
271 ++i;
272 }
273 }
274 BENCHMARK(BM_Duration_IDivDuration_Minutes);
275
BM_Duration_IDivDuration_Hours(benchmark::State & state)276 void BM_Duration_IDivDuration_Hours(benchmark::State& state) {
277 int64_t a = 1;
278 absl::Duration ignore;
279 int i = 0;
280 while (state.KeepRunning()) {
281 benchmark::DoNotOptimize(
282 a += absl::IDivDuration(absl::Hours(i), absl::Hours(1), &ignore));
283 ++i;
284 }
285 }
286 BENCHMARK(BM_Duration_IDivDuration_Hours);
287
BM_Duration_ToInt64Nanoseconds(benchmark::State & state)288 void BM_Duration_ToInt64Nanoseconds(benchmark::State& state) {
289 absl::Duration d = absl::Seconds(100000);
290 while (state.KeepRunning()) {
291 benchmark::DoNotOptimize(absl::ToInt64Nanoseconds(d));
292 }
293 }
294 BENCHMARK(BM_Duration_ToInt64Nanoseconds);
295
BM_Duration_ToInt64Microseconds(benchmark::State & state)296 void BM_Duration_ToInt64Microseconds(benchmark::State& state) {
297 absl::Duration d = absl::Seconds(100000);
298 while (state.KeepRunning()) {
299 benchmark::DoNotOptimize(absl::ToInt64Microseconds(d));
300 }
301 }
302 BENCHMARK(BM_Duration_ToInt64Microseconds);
303
BM_Duration_ToInt64Milliseconds(benchmark::State & state)304 void BM_Duration_ToInt64Milliseconds(benchmark::State& state) {
305 absl::Duration d = absl::Seconds(100000);
306 while (state.KeepRunning()) {
307 benchmark::DoNotOptimize(absl::ToInt64Milliseconds(d));
308 }
309 }
310 BENCHMARK(BM_Duration_ToInt64Milliseconds);
311
BM_Duration_ToInt64Seconds(benchmark::State & state)312 void BM_Duration_ToInt64Seconds(benchmark::State& state) {
313 absl::Duration d = absl::Seconds(100000);
314 while (state.KeepRunning()) {
315 benchmark::DoNotOptimize(absl::ToInt64Seconds(d));
316 }
317 }
318 BENCHMARK(BM_Duration_ToInt64Seconds);
319
BM_Duration_ToInt64Minutes(benchmark::State & state)320 void BM_Duration_ToInt64Minutes(benchmark::State& state) {
321 absl::Duration d = absl::Seconds(100000);
322 while (state.KeepRunning()) {
323 benchmark::DoNotOptimize(absl::ToInt64Minutes(d));
324 }
325 }
326 BENCHMARK(BM_Duration_ToInt64Minutes);
327
BM_Duration_ToInt64Hours(benchmark::State & state)328 void BM_Duration_ToInt64Hours(benchmark::State& state) {
329 absl::Duration d = absl::Seconds(100000);
330 while (state.KeepRunning()) {
331 benchmark::DoNotOptimize(absl::ToInt64Hours(d));
332 }
333 }
334 BENCHMARK(BM_Duration_ToInt64Hours);
335
336 //
337 // To/FromTimespec
338 //
339
BM_Duration_ToTimespec_AbslTime(benchmark::State & state)340 void BM_Duration_ToTimespec_AbslTime(benchmark::State& state) {
341 absl::Duration d = absl::Seconds(1);
342 while (state.KeepRunning()) {
343 benchmark::DoNotOptimize(absl::ToTimespec(d));
344 }
345 }
346 BENCHMARK(BM_Duration_ToTimespec_AbslTime);
347
DoubleToTimespec(double seconds)348 ABSL_ATTRIBUTE_NOINLINE timespec DoubleToTimespec(double seconds) {
349 timespec ts;
350 ts.tv_sec = seconds;
351 ts.tv_nsec = (seconds - ts.tv_sec) * (1000 * 1000 * 1000);
352 return ts;
353 }
354
BM_Duration_ToTimespec_Double(benchmark::State & state)355 void BM_Duration_ToTimespec_Double(benchmark::State& state) {
356 while (state.KeepRunning()) {
357 benchmark::DoNotOptimize(DoubleToTimespec(1.0));
358 }
359 }
360 BENCHMARK(BM_Duration_ToTimespec_Double);
361
BM_Duration_FromTimespec_AbslTime(benchmark::State & state)362 void BM_Duration_FromTimespec_AbslTime(benchmark::State& state) {
363 timespec ts;
364 ts.tv_sec = 0;
365 ts.tv_nsec = 0;
366 while (state.KeepRunning()) {
367 if (++ts.tv_nsec == 1000 * 1000 * 1000) {
368 ++ts.tv_sec;
369 ts.tv_nsec = 0;
370 }
371 benchmark::DoNotOptimize(absl::DurationFromTimespec(ts));
372 }
373 }
374 BENCHMARK(BM_Duration_FromTimespec_AbslTime);
375
TimespecToDouble(timespec ts)376 ABSL_ATTRIBUTE_NOINLINE double TimespecToDouble(timespec ts) {
377 return ts.tv_sec + (ts.tv_nsec / (1000 * 1000 * 1000));
378 }
379
BM_Duration_FromTimespec_Double(benchmark::State & state)380 void BM_Duration_FromTimespec_Double(benchmark::State& state) {
381 timespec ts;
382 ts.tv_sec = 0;
383 ts.tv_nsec = 0;
384 while (state.KeepRunning()) {
385 if (++ts.tv_nsec == 1000 * 1000 * 1000) {
386 ++ts.tv_sec;
387 ts.tv_nsec = 0;
388 }
389 benchmark::DoNotOptimize(TimespecToDouble(ts));
390 }
391 }
392 BENCHMARK(BM_Duration_FromTimespec_Double);
393
394 //
395 // String conversions
396 //
397
398 const char* const kDurations[] = {
399 "0", // 0
400 "123ns", // 1
401 "1h2m3s", // 2
402 "-2h3m4.005006007s", // 3
403 "2562047788015215h30m7.99999999975s", // 4
404 };
405 const int kNumDurations = sizeof(kDurations) / sizeof(kDurations[0]);
406
BM_Duration_FormatDuration(benchmark::State & state)407 void BM_Duration_FormatDuration(benchmark::State& state) {
408 const std::string s = kDurations[state.range(0)];
409 state.SetLabel(s);
410 absl::Duration d;
411 absl::ParseDuration(kDurations[state.range(0)], &d);
412 while (state.KeepRunning()) {
413 benchmark::DoNotOptimize(absl::FormatDuration(d));
414 }
415 }
416 BENCHMARK(BM_Duration_FormatDuration)->DenseRange(0, kNumDurations - 1);
417
BM_Duration_ParseDuration(benchmark::State & state)418 void BM_Duration_ParseDuration(benchmark::State& state) {
419 const std::string s = kDurations[state.range(0)];
420 state.SetLabel(s);
421 absl::Duration d;
422 while (state.KeepRunning()) {
423 benchmark::DoNotOptimize(absl::ParseDuration(s, &d));
424 }
425 }
426 BENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1);
427
428 } // namespace
429