• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&timestamp, &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