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 "cstdlib"
17 #include "cstdio"
18 #include "cstring"
19 #include "fcntl.h"
20 #include "unistd.h"
21 #include "cwchar"
22 #include "clocale"
23 #include "util.h"
24
25 using namespace std;
26
27 using Nier = struct {
28 char name[20];
29 int age;
30 };
31
32 static const vector<int> memalignLength {
33 8,
34 16,
35 64,
36 1 * K,
37 4 * K,
38 64 * K,
39 256 * K,
40 1 * M,
41 4 * M,
42 64 * M,
43 256 * M,
44 1 * G,
45 };
46
47 static const vector<int> memalignAlign {
48 8,
49 16,
50 64,
51 256,
52 1 * K,
53 4 * K,
54 64 * K,
55 256 * K,
56 1 * M,
57 };
58
PrepareArgsMemalign(benchmark::internal::Benchmark * b)59 static void PrepareArgsMemalign(benchmark::internal::Benchmark* b)
60 {
61 for (auto a : memalignAlign) {
62 for (auto l : memalignLength) {
63 if (l >= a && l % a == 0) {
64 b->Args({a, l});
65 }
66 }
67 }
68 }
69
CompareInt(const void * a,const void * b)70 int CompareInt(const void *a, const void *b)
71 {
72 int c = *(int *)a;
73 int d = *(int *)b;
74 if (c < d) {
75 return -1;
76 } else if (c > d) {
77 return 1;
78 } else {
79 return 0;
80 }
81 }
82
CompareDouble(const void * a,const void * b)83 int CompareDouble(const void *a, const void *b)
84 {
85 double c = *(double *)a;
86 double d = *(double *)b;
87 if (c == d) {
88 return 0;
89 } else if (c > d) {
90 return 1;
91 } else {
92 return -1;
93 }
94 }
95
CompareString(const void * a,const void * b)96 int CompareString(const void *a, const void *b)
97 {
98 const char* c = (char *)a;
99 const char* d = (char *)b;
100 return strcmp(c, d);
101 }
102
CompareStruct(const void * a,const void * b)103 int CompareStruct(const void *a, const void *b)
104 {
105 return strcmp(((Nier *)a)->name, ((Nier *)b)->name);
106 }
107
InitRandomArray(int * arr,size_t n)108 void InitRandomArray(int *arr, size_t n)
109 {
110 for (size_t i = 0; i < n; i++) {
111 arr[i] = rand() % (2 * n);
112 }
113 }
114
115 // Convert the string pointed to by str to floating point
Bm_function_Strtod(benchmark::State & state)116 static void Bm_function_Strtod(benchmark::State &state)
117 {
118 const char *var[] = { "+2.86500000e+01", "3.1415", "29",
119 "-123.456", "1.23e5", "0x1.2p3",
120 "-inf", "123foo" };
121 const char *str = var[state.range(0)];
122 char *ptr;
123 for (auto _ : state) {
124 benchmark::DoNotOptimize(strtod(str, &ptr));
125 }
126 }
127
Bm_function_Strtof(benchmark::State & state)128 static void Bm_function_Strtof(benchmark::State &state)
129 {
130 const char *var[] = {"+2.86500000e+01", "3.1415", "29",
131 "-123.456", "1.23e5", "0x1.2p3",
132 "-inf", "123foo"};
133 const char *str = var[state.range(0)];
134 char *ptr;
135 for (auto _ : state) {
136 benchmark::DoNotOptimize(strtof(str, &ptr));
137 }
138 }
139
Bm_function_Strtold(benchmark::State & state)140 static void Bm_function_Strtold(benchmark::State &state)
141 {
142 const char *var[] = {"+2.86500000e+01", "3.1415", "29",
143 "-123.456", "1.23e5", "0x1.2p3",
144 "-inf", "123foo"};
145 const char *str = var[state.range(0)];
146 char *ptr;
147 for (auto _ : state) {
148 benchmark::DoNotOptimize(strtold(str, &ptr));
149 }
150 }
151
152 // Used to sort elements in an array
153 // int type
Bm_function_Qsortint(benchmark::State & state)154 static void Bm_function_Qsortint(benchmark::State &state)
155 {
156 for (auto _ : state) {
157 int arr[] = { 12, 89, 5, 3, 7, 1, 9, 2, 6 };
158 int n = sizeof(arr) / sizeof(arr[0]);
159 qsort(arr, n, sizeof(int), CompareInt);
160 }
161 }
162
163 // double type
Bm_function_Qsortdouble(benchmark::State & state)164 static void Bm_function_Qsortdouble(benchmark::State &state)
165 {
166 for (auto _ : state) {
167 double arr[] = { 34.541, 5.32, 3.56, 7.897, 1.2324, 9.34543, 5.324, 98.543, 34.665 };
168 int n = sizeof(arr) / sizeof(arr[0]);
169 qsort(arr, n, sizeof(double), CompareDouble);
170 }
171 }
172
173 // string type
Bm_function_Qsortstring(benchmark::State & state)174 static void Bm_function_Qsortstring(benchmark::State &state)
175 {
176 for (auto _ : state) {
177 const char *arr[] = { "nihuangela", "xiaozhenhuniang", "our story",
178 "a language", "love", "qluhanagala",
179 "for elun", "sakuruwuma", "benchmark_musl" };
180 int n = sizeof(arr) / sizeof(arr[0]);
181 qsort(arr, n, sizeof(char *), CompareString);
182 }
183 }
184
185 // struct type
Bm_function_Qsortstruct(benchmark::State & state)186 static void Bm_function_Qsortstruct(benchmark::State &state)
187 {
188 const int len = 9;
189 for (auto _ : state) {
190 Nier nidate[len] = { {"Meihuagao", 23}, {"Sdifenzhou", 68}, {"Amusterlang", 99},
191 {"elun", 56}, {"yishinuala", 120}, {"huajiahaochi", 22},
192 {"lunala", 66}, {"cocolou", 77}, {"xinnoqikala", 55} };
193 qsort(nidate, len, sizeof(Nier), CompareStruct);
194 }
195 }
196
Bm_function_Qsort_random(benchmark::State & state)197 static void Bm_function_Qsort_random(benchmark::State &state)
198 {
199 srand(1);
200 int n = state.range(0);
201 int *arr1 = new int[n];
202 int *arr2 = new int[n];
203 InitRandomArray(arr1, n);
204
205 for (auto _ : state)
206 {
207 state.PauseTiming();
208 memcpy(arr2, arr1, n);
209 state.ResumeTiming();
210 qsort(arr2, n, sizeof(int), CompareInt);
211 }
212
213 delete[] arr1;
214 delete[] arr2;
215 }
216
Bm_function_Getenv_TZ(benchmark::State & state)217 static void Bm_function_Getenv_TZ(benchmark::State &state)
218 {
219 for (auto _ : state) {
220 benchmark::DoNotOptimize(getenv("TZ"));
221 }
222 }
223
Bm_function_Getenv_LD_LIBRARY_PATH(benchmark::State & state)224 static void Bm_function_Getenv_LD_LIBRARY_PATH(benchmark::State &state)
225 {
226 for (auto _ : state) {
227 benchmark::DoNotOptimize(getenv("LD_LIBRARY_PATH"));
228 }
229 }
230
Bm_function_Getenv_LD_PRELOAD(benchmark::State & state)231 static void Bm_function_Getenv_LD_PRELOAD(benchmark::State &state)
232 {
233 for (auto _ : state) {
234 benchmark::DoNotOptimize(getenv("LD_PRELOAD"));
235 }
236 }
237
Bm_function_Getenv_LC_ALL(benchmark::State & state)238 static void Bm_function_Getenv_LC_ALL(benchmark::State &state)
239 {
240 for (auto _ : state) {
241 benchmark::DoNotOptimize(getenv("LC_ALL"));
242 }
243 }
244
Bm_function_Getenv_LOGNAME(benchmark::State & state)245 static void Bm_function_Getenv_LOGNAME(benchmark::State &state)
246 {
247 for (auto _ : state) {
248 benchmark::DoNotOptimize(getenv("LOGNAME"));
249 }
250 }
251
252 // Converts any relative path to an absolute path
Bm_function_Realpath(benchmark::State & state)253 static void Bm_function_Realpath(benchmark::State &state)
254 {
255 const int bufferLen = 4096;
256 const char *realpathvariable[] = { "./log", "../dev", "log/hilog", "../dev/zero", "/dev" };
257 const char *path = realpathvariable[state.range(0)];
258 char resolvedPath[bufferLen];
259 for (auto _ : state) {
260 benchmark::DoNotOptimize(realpath(path, resolvedPath));
261 }
262 }
263
Bm_function_Posix_Memalign(benchmark::State & state)264 static void Bm_function_Posix_Memalign(benchmark::State &state)
265 {
266 size_t align = state.range(0);
267 size_t length = state.range(1);
268 for (auto _ : state) {
269 void *buf = nullptr;
270 int ret = posix_memalign(&buf, align, length);
271 if (ret) {
272 perror("posix_memalign failed");
273 }
274
275 state.PauseTiming();
276 free(buf);
277 state.ResumeTiming();
278 }
279 }
280
Bm_function_Mkostemps(benchmark::State & state)281 static void Bm_function_Mkostemps(benchmark::State &state)
282 {
283 char fileTemplate[] = "/tmp/mkostemps-XXXXXX-test";
284 for (auto _ : state) {
285 int fd = mkostemps(fileTemplate, 5, O_SYNC);
286 if (fd >= 0) {
287 unlink(fileTemplate);
288 close(fd);
289 }
290 }
291 }
292
293 // Generate a random number seed and receive a sequence of random numbers
Bm_function_Srand48_Lrand48(benchmark::State & state)294 static void Bm_function_Srand48_Lrand48(benchmark::State &state)
295 {
296 for (auto _ : state) {
297 srand48(time(nullptr));
298 benchmark::DoNotOptimize(lrand48());
299 }
300 }
301
302 // Customize the value of the environment variable and delete it
Bm_function_Putenv_Unsetenv(benchmark::State & state)303 static void Bm_function_Putenv_Unsetenv(benchmark::State &state)
304 {
305 const char *putpath[] = { "TEST_A=/usr/local/myapp", "TEST_B=/bin/yes", "TEST_C=/usr/local/bin:/usr/bin:/bin",
306 "TEST_D=vim", "TEST_E=hello", "TEST_F=en_US.UTF-8", "TEST_G=myname",
307 "TEST_H=nichenzhan" };
308 const char *unsetpath[] = { "TEST_A", "TEST_B", "TEST_C", "TEST_D",
309 "TEST_E", "TEST_F", "TEST_G", "TEST_H" };
310 const char *a = putpath[state.range(0)];
311 const char *b = unsetpath[state.range(0)];
312 for (auto _ : state) {
313 benchmark::DoNotOptimize(putenv((char*)a));
314 benchmark::DoNotOptimize(unsetenv(b));
315 }
316 }
317
Bm_function_Wcstombs(benchmark::State & state)318 static void Bm_function_Wcstombs(benchmark::State &state)
319 {
320 setlocale(LC_ALL, "");
321 const wchar_t wstr[] = L"z\u00df\u6c34\U0001f34c";
322 size_t len = wcslen(wstr);
323 char *str = (char*)malloc(sizeof(char) * (len + 1));
324 for (auto _ : state) {
325 benchmark::DoNotOptimize(wcstombs(str, wstr, len));
326 }
327 free(str);
328 }
329
ExitFunc()330 void ExitFunc(){};
Bm_function_cxa_atexit(benchmark::State & state)331 static void Bm_function_cxa_atexit(benchmark::State &state)
332 {
333 for (auto _ : state) {
334 benchmark::DoNotOptimize(atexit(ExitFunc));
335 }
336 }
337
Bm_function_Srandom(benchmark::State & state)338 static void Bm_function_Srandom(benchmark::State &state)
339 {
340 unsigned int seed = static_cast<unsigned int>(time(nullptr));
341 for (auto _ : state) {
342 srandom(seed);
343 }
344 }
345
346 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strtod, "BENCHMARK_8");
347 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strtof, "BENCHMARK_8");
348 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strtold, "BENCHMARK_8");
349 MUSL_BENCHMARK(Bm_function_Qsortint);
350 MUSL_BENCHMARK(Bm_function_Qsortdouble);
351 MUSL_BENCHMARK(Bm_function_Qsortstring);
352 MUSL_BENCHMARK(Bm_function_Qsortstruct);
353 MUSL_BENCHMARK_WITH_ARG(Bm_function_Qsort_random, "COMMON_ARGS");
354 MUSL_BENCHMARK_WITH_ARG(Bm_function_Realpath, "BENCHMARK_5");
355 MUSL_BENCHMARK(Bm_function_Getenv_TZ);
356 MUSL_BENCHMARK(Bm_function_Getenv_LD_LIBRARY_PATH);
357 MUSL_BENCHMARK(Bm_function_Getenv_LD_PRELOAD);
358 MUSL_BENCHMARK(Bm_function_Getenv_LC_ALL);
359 MUSL_BENCHMARK(Bm_function_Getenv_LOGNAME);
360 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Posix_Memalign, PrepareArgsMemalign);
361 MUSL_BENCHMARK(Bm_function_Mkostemps);
362 MUSL_BENCHMARK(Bm_function_Srand48_Lrand48);
363 MUSL_BENCHMARK_WITH_ARG(Bm_function_Putenv_Unsetenv, "BENCHMARK_8");
364 MUSL_BENCHMARK(Bm_function_Wcstombs);
365 MUSL_BENCHMARK(Bm_function_cxa_atexit);
366 MUSL_BENCHMARK(Bm_function_Srandom);
367