1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2023. All rights reserved.
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 * http://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
16 #include "ctime"
17 #if not defined __APPLE__
18 #include "sys/timerfd.h"
19 #endif
20 #include "sys/time.h"
21 #include "cstdlib"
22 #include "cstdio"
23 #include "csignal"
24 #include "unistd.h"
25 #include "util.h"
26
27 using namespace std;
28 constexpr int TEN = 10;
29 constexpr int HUNDRED = 100;
30 // Used to put the current thread to sleep for the specified time
Bm_function_Nanosleep_0ns(benchmark::State & state)31 static void Bm_function_Nanosleep_0ns(benchmark::State &state)
32 {
33 struct timespec req, rem;
34 req.tv_nsec = 0;
35 for (auto _ : state) {
36 benchmark::DoNotOptimize(nanosleep(&req, &rem));
37 }
38 }
39
Bm_function_Nanosleep_10ns(benchmark::State & state)40 static void Bm_function_Nanosleep_10ns(benchmark::State &state)
41 {
42 struct timespec req, rem;
43 req.tv_nsec = TEN;
44 for (auto _ : state) {
45 benchmark::DoNotOptimize(nanosleep(&req, &rem));
46 }
47 }
48
Bm_function_Nanosleep_100ns(benchmark::State & state)49 static void Bm_function_Nanosleep_100ns(benchmark::State &state)
50 {
51 struct timespec req, rem;
52 req.tv_nsec = HUNDRED;
53 for (auto _ : state) {
54 benchmark::DoNotOptimize(nanosleep(&req, &rem));
55 }
56 }
57
58 // Used to set information about the time zone
Bm_function_Tzset(benchmark::State & state)59 static void Bm_function_Tzset(benchmark::State &state)
60 {
61 while (state.KeepRunning()) {
62 tzset();
63 }
64 }
Bm_function_Clock_nanosleep_realtime(benchmark::State & state)65 static void Bm_function_Clock_nanosleep_realtime(benchmark::State &state)
66 {
67 struct timespec req, rem;
68 req.tv_nsec = TEN;
69 for (auto _ : state) {
70 benchmark::DoNotOptimize(clock_nanosleep(CLOCK_REALTIME, 0, &req, &rem));
71 }
72 }
73
Bm_function_Clock_nanosleep_realtime_raw(benchmark::State & state)74 static void Bm_function_Clock_nanosleep_realtime_raw(benchmark::State &state)
75 {
76 struct timespec req, rem;
77 req.tv_nsec = TEN;
78 for (auto _ : state) {
79 benchmark::DoNotOptimize(clock_nanosleep(CLOCK_REALTIME_COARSE, 0, &req, &rem));
80 }
81 }
82
Bm_function_Clock_nanosleep_realtime_coarse(benchmark::State & state)83 static void Bm_function_Clock_nanosleep_realtime_coarse(benchmark::State &state)
84 {
85 struct timespec req, rem;
86 req.tv_nsec = TEN;
87 for (auto _ : state) {
88 benchmark::DoNotOptimize(clock_nanosleep(CLOCK_REALTIME_COARSE, 0, &req, &rem));
89 }
90 }
91
Bm_function_Clock_nanosleep_monotonic(benchmark::State & state)92 static void Bm_function_Clock_nanosleep_monotonic(benchmark::State &state)
93 {
94 struct timespec req, rem;
95 req.tv_nsec = TEN;
96 for (auto _ : state) {
97 benchmark::DoNotOptimize(clock_nanosleep(CLOCK_MONOTONIC, 0, &req, &rem));
98 }
99 }
Bm_function_Clock_nanosleep_monotonic_coarse(benchmark::State & state)100 static void Bm_function_Clock_nanosleep_monotonic_coarse(benchmark::State &state)
101 {
102 struct timespec req, rem;
103 req.tv_nsec = TEN;
104 for (auto _ : state) {
105 benchmark::DoNotOptimize(clock_nanosleep(CLOCK_MONOTONIC_COARSE, 0, &req, &rem));
106 }
107 }
Bm_function_Clock_nanosleep_monotonic_raw(benchmark::State & state)108 static void Bm_function_Clock_nanosleep_monotonic_raw(benchmark::State &state)
109 {
110 struct timespec req, rem;
111 req.tv_nsec = TEN;
112 for (auto _ : state) {
113 benchmark::DoNotOptimize(clock_nanosleep(CLOCK_MONOTONIC_RAW, 0, &req, &rem));
114 }
115 }
Bm_function_Clock_nanosleep_boottime(benchmark::State & state)116 static void Bm_function_Clock_nanosleep_boottime(benchmark::State &state)
117 {
118 struct timespec req, rem;
119 req.tv_nsec = TEN;
120 for (auto _ : state) {
121 benchmark::DoNotOptimize(clock_nanosleep(CLOCK_BOOTTIME, 0, &req, &rem));
122 }
123 }
124
125 constexpr int BUFFER_SIZE = 32;
126
Bm_function_Strftime(benchmark::State & state)127 static void Bm_function_Strftime(benchmark::State &state)
128 {
129 time_t rawTime = time(nullptr);
130 struct tm *localTime = localtime(&rawTime);
131 char buf[BUFFER_SIZE];
132 while (state.KeepRunning()) {
133 benchmark::DoNotOptimize(strftime(buf, BUFFER_SIZE, "%Y-%m-%d %H:%M:%S", localTime));
134 }
135 }
136
Bm_function_Mktime(benchmark::State & state)137 static void Bm_function_Mktime(benchmark::State &state)
138 {
139 time_t rawTime = time(nullptr);
140 struct tm *localTime = localtime(&rawTime);
141 while (state.KeepRunning()) {
142 benchmark::DoNotOptimize(mktime(localTime));
143 }
144 }
145
Bm_function_Gmtime(benchmark::State & state)146 static void Bm_function_Gmtime(benchmark::State &state)
147 {
148 time_t rawTime = time(nullptr);
149 while (state.KeepRunning()) {
150 benchmark::DoNotOptimize(gmtime(&rawTime));
151 }
152 }
153
Bm_function_Timerfd_settime(benchmark::State & state)154 static void Bm_function_Timerfd_settime(benchmark::State &state)
155 {
156 int fd = timerfd_create(CLOCK_REALTIME, 0);
157 if (fd < 0) {
158 perror("timerfd_create");
159 }
160
161 struct timespec now;
162 struct itimerspec newValue;
163 if (clock_gettime(CLOCK_REALTIME, &now) == -1) {
164 perror("clock_gettime");
165 }
166
167 newValue.it_value.tv_sec = now.tv_sec + 3;
168 newValue.it_value.tv_nsec = now.tv_nsec;
169 newValue.it_interval.tv_sec = 0;
170 newValue.it_interval.tv_nsec = 0;
171
172 while (state.KeepRunning()) {
173 if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &newValue, nullptr) == -1) {
174 perror("timerfd_settime");
175 }
176 }
177
178 close(fd);
179 }
180
181 // Converts a timestamp of a time_t type to a readable string representation
Bm_function_Ctime_r(benchmark::State & state)182 static void Bm_function_Ctime_r(benchmark::State &state)
183 {
184 time_t t = time(nullptr);
185 for (auto _ : state) {
186 char buf[100] = {0};
187 benchmark::DoNotOptimize(ctime_r(&t, buf));
188 }
189 }
190
HandleTimer(int signum)191 void HandleTimer(int signum)
192 {
193 switch (signum) {
194 case SIGALRM:
195 // do nothing
196 break;
197 case SIGVTALRM:
198 // do nothing
199 break;
200 case SIGPROF:
201 // do nothing
202 break;
203 default:
204 break;
205 }
206 }
207
208 // Used to set the timer
209 // ITIMER_REAL timing mode
Bm_function_Setitimer_realtime(benchmark::State & state)210 static void Bm_function_Setitimer_realtime(benchmark::State &state)
211 {
212 struct itimerval timer;
213 timer.it_value.tv_sec = 1;
214 timer.it_value.tv_usec = 0;
215 timer.it_interval.tv_sec = 1;
216 timer.it_interval.tv_usec = 0;
217
218 for (auto _ : state) {
219 signal(SIGALRM, HandleTimer);
220 if (setitimer(ITIMER_REAL, &timer, nullptr) == -1) {
221 perror("Set timer error!");
222 }
223 benchmark::DoNotOptimize(timer);
224 }
225 }
226
227 // ITIMER_PROF timing mode
Bm_function_Setitimer_peoftime(benchmark::State & state)228 static void Bm_function_Setitimer_peoftime(benchmark::State &state)
229 {
230 struct itimerval timer;
231 timer.it_value.tv_sec = 1;
232 timer.it_value.tv_usec = 0;
233 timer.it_interval.tv_sec = 1;
234 timer.it_interval.tv_usec = 0;
235
236 for (auto _ : state) {
237 signal(SIGPROF, HandleTimer);
238 if (setitimer(ITIMER_PROF, &timer, nullptr) == -1) {
239 perror("Set timer error!");
240 }
241 benchmark::DoNotOptimize(timer);
242 }
243 }
244
245 // ITIMER_VIRTUAL timing mode
Bm_function_Setitimer_virtualtime(benchmark::State & state)246 static void Bm_function_Setitimer_virtualtime(benchmark::State &state)
247 {
248 struct itimerval timer;
249 timer.it_value.tv_sec = 1;
250 timer.it_value.tv_usec = 0;
251 timer.it_interval.tv_sec = 1;
252 timer.it_interval.tv_usec = 0;
253
254 for (auto _ : state) {
255 signal(SIGVTALRM, HandleTimer);
256 if (setitimer(ITIMER_VIRTUAL, &timer, nullptr) == -1) {
257 perror("Set timer error!");
258 }
259 benchmark::DoNotOptimize(timer);
260 }
261 }
262
Handler(int signum)263 static void Handler(int signum)
264 {
265 // do nothing
266 }
267
268 // Use the timer function to create a timer
Bm_function_Timer(benchmark::State & state)269 static void Bm_function_Timer(benchmark::State &state)
270 {
271 timer_t timerid;
272 struct sigevent evp;
273 struct itimerspec itVal;
274 int ret;
275
276 evp.sigev_value.sival_ptr = &timerid;
277 evp.sigev_notify = SIGEV_SIGNAL;
278 evp.sigev_signo = SIGUSR1;
279
280 itVal.it_value.tv_sec = 1;
281 itVal.it_value.tv_nsec = 0;
282 itVal.it_interval.tv_sec = 1;
283 itVal.it_interval.tv_nsec = 0;
284
285 for (auto _ : state) {
286 ret = timer_create(CLOCK_REALTIME, &evp, &timerid);
287 if (ret) {
288 perror("timer_create");
289 }
290
291 ret = timer_settime(timerid, 0, &itVal, nullptr);
292 if (ret) {
293 perror("timer_settime");
294 }
295
296 signal(SIGUSR1, Handler);
297
298 ret = timer_delete(timerid);
299 if (ret) {
300 perror("timer_delete");
301 }
302 }
303 }
304
Bm_function_Asctime(benchmark::State & state)305 static void Bm_function_Asctime(benchmark::State &state)
306 {
307 struct tm tmTime = {
308 .tm_year = 90,
309 .tm_mon = 1,
310 .tm_mday = 12,
311 .tm_hour = 20,
312 .tm_min = 0,
313 .tm_sec = 04,
314 .tm_isdst = -1,
315 };
316
317 for (auto _ : state) {
318 benchmark::DoNotOptimize(asctime(&tmTime));
319 }
320 }
321
Bm_function_Gmtime_r(benchmark::State & state)322 static void Bm_function_Gmtime_r(benchmark::State &state)
323 {
324 time_t timestamp = time(nullptr);
325 struct tm result;
326 for (auto _ : state) {
327 benchmark::DoNotOptimize(gmtime_r(×tamp, &result));
328 }
329 }
330
Bm_function_Timegm(benchmark::State & state)331 static void Bm_function_Timegm(benchmark::State &state)
332 {
333 struct tm tmTime = {
334 .tm_year = 90,
335 .tm_mon = 1,
336 .tm_mday = 12,
337 .tm_hour = 20,
338 .tm_min = 0,
339 .tm_sec = 04,
340 .tm_isdst = -1,
341 };
342
343 for (auto _ : state) {
344 benchmark::DoNotOptimize(timegm(&tmTime));
345 }
346 }
347
348 // Converts a string to a time based on a different time zone
Bm_function_Strptime(benchmark::State & state)349 static void Bm_function_Strptime(benchmark::State &state)
350 {
351 const char *formatsrc[] = { "%c", "%c %Z%z", "%D", "%F", "%g", "%k", "%l", "%s", "%u",
352 "%v", "%G", "%j", "%P", "%U", "%w", "%V", "%R", "%r", "%T",
353 "%x", "%X", "%%" };
354 const char *format = formatsrc[state.range(0)];
355 time_t rawTime = time(nullptr);
356 struct tm *localTime = localtime(&rawTime);
357 char buf[BUFFER_SIZE];
358 strftime(buf, BUFFER_SIZE, format, localTime);
359 while (state.KeepRunning()) {
360 benchmark::DoNotOptimize(strptime(buf, format, localTime));
361 }
362 }
363
364 MUSL_BENCHMARK(Bm_function_Nanosleep_0ns);
365 MUSL_BENCHMARK(Bm_function_Nanosleep_10ns);
366 MUSL_BENCHMARK(Bm_function_Nanosleep_100ns);
367 MUSL_BENCHMARK(Bm_function_Tzset);
368 MUSL_BENCHMARK(Bm_function_Clock_nanosleep_realtime);
369 MUSL_BENCHMARK(Bm_function_Clock_nanosleep_realtime_raw);
370 MUSL_BENCHMARK(Bm_function_Clock_nanosleep_realtime_coarse);
371 MUSL_BENCHMARK(Bm_function_Clock_nanosleep_monotonic);
372 MUSL_BENCHMARK(Bm_function_Clock_nanosleep_monotonic_raw);
373 MUSL_BENCHMARK(Bm_function_Clock_nanosleep_monotonic_coarse);
374 MUSL_BENCHMARK(Bm_function_Clock_nanosleep_boottime);
375 MUSL_BENCHMARK(Bm_function_Strftime);
376 MUSL_BENCHMARK(Bm_function_Mktime);
377 MUSL_BENCHMARK(Bm_function_Gmtime);
378 MUSL_BENCHMARK(Bm_function_Timerfd_settime);
379 MUSL_BENCHMARK(Bm_function_Ctime_r);
380 MUSL_BENCHMARK(Bm_function_Setitimer_realtime);
381 MUSL_BENCHMARK(Bm_function_Setitimer_peoftime);
382 MUSL_BENCHMARK(Bm_function_Setitimer_virtualtime);
383 MUSL_BENCHMARK(Bm_function_Timer);
384 MUSL_BENCHMARK(Bm_function_Asctime);
385 MUSL_BENCHMARK(Bm_function_Gmtime_r);
386 MUSL_BENCHMARK(Bm_function_Timegm);
387 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strptime, "BENCHMARK_22");
388
389