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 #include <iostream>
16 #if not defined __APPLE__
17 #include <stdio_ext.h>
18 #endif
19 #include <unistd.h>
20 #include <thread>
21 #include "cstring"
22 #include "cwchar"
23 #include "err.h"
24 #include "cerrno"
25 #include "clocale"
26 #include "util.h"
27 #include <stdio_ext.h>
28 #include <unistd.h>
29 #include <thread>
30 #include <iostream>
31
32 using namespace std;
33
34 static const std::vector<int> bufferSizes {
35 8,
36 16,
37 32,
38 64,
39 512,
40 1 * K,
41 8 * K,
42 16 * K,
43 32 * K,
44 64 * K,
45 128 * K,
46 };
47
48 static const std::vector<int> limitSizes {
49 1,
50 8,
51 64,
52 1 * K,
53 16 * K,
54 64 * K,
55 128 * K,
56 };
57
StringtestArgs(benchmark::internal::Benchmark * b)58 static void StringtestArgs(benchmark::internal::Benchmark* b)
59 {
60 for (auto l : bufferSizes) {
61 for (auto f : limitSizes) {
62 if (f > l) {
63 b->Args({l, l, 0});
64 } else {
65 b->Args({l, f, 0});
66 }
67 }
68 }
69 }
70
71 // Searches for the first occurrence of the character x in the first n bytes of the selected string
Bm_function_Memchr(benchmark::State & state)72 static void Bm_function_Memchr(benchmark::State &state)
73 {
74 const size_t nbytes = state.range(0);
75 const size_t limitsize = state.range(1);
76 const size_t bmmemchrAlignment = state.range(2);
77 vector<char> bmmemchr;
78 char *bmmemchrAligned = GetAlignedPtrFilled(&bmmemchr, bmmemchrAlignment, nbytes, 'n');
79 bmmemchrAligned[nbytes - 1] = '\0';
80 while (state.KeepRunning()) {
81 if (memchr(bmmemchrAligned, 'x', limitsize) != nullptr) {
82 errx(1, "ERROR: memchr found a chr where it should have failed.");
83 }
84 }
85 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
86 }
87
88 // Finds the last occurrence of the specified character in a string and returns a pointer to that position
Bm_function_Strrchr(benchmark::State & state)89 static void Bm_function_Strrchr(benchmark::State &state)
90 {
91 const char *strrchrtestsrc[] = { "com.ohos.launcher", "/system/lib/libfilemgmt_libhilog.z.so",
92 "/system/lib/libstatic_subscriber_extension.z.so",
93 "../../base/startup/init/services/param/base/param_base.c",
94 "/system/lib/libwallpapermanager.z.so",
95 "/system/lib/libwallpaperextension.z.so",
96 "/system/lib/module/libaccessibility.z.so",
97 "/../base/startup/init/services/param/base/param_trie.c" };
98 const char strrchrtesttag[] = { 'm', 'l', 's', 'o', 'z', 't', 'i', 'c', '\0' };
99 const char *test = strrchrtestsrc[state.range(0)];
100 const char ch = strrchrtesttag[state.range(0)];
101 for (auto _ : state) {
102 benchmark::DoNotOptimize(strrchr(test, ch));
103 }
104 state.SetBytesProcessed(state.iterations());
105 }
106
107 // The selected range calculates the length
Bm_function_Strnlen(benchmark::State & state)108 static void Bm_function_Strnlen(benchmark::State &state)
109 {
110 const size_t nbytes = state.range(0);
111 const size_t limitsize = state.range(1);
112 const size_t bmstrnlenAlignment = state.range(2);
113 vector<char> bmstrnlen;
114 char *bmstrnlenAligned = GetAlignedPtrFilled(&bmstrnlen, bmstrnlenAlignment, nbytes + 1, 'n');
115 bmstrnlenAligned[nbytes - 1] = '\0';
116
117 volatile int c __attribute__((unused)) = 0;
118 while (state.KeepRunning()) {
119 c += strnlen(bmstrnlenAligned, limitsize);
120 }
121 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
122 }
123 #if not defined __APPLE__
124 extern "C" size_t __strlen_chk(const char* s, size_t s_len);
125
Bm_function_Strlen_chk(benchmark::State & state)126 static void Bm_function_Strlen_chk(benchmark::State& state)
127 {
128 const size_t nbytes = bufferSizes[state.range(0)];
129 vector<char> bmstrlen;
130 char *bmstrlenAligned = GetAlignedPtrFilled(&bmstrlen, 0, nbytes + 1, 'n');
131 bmstrlenAligned[nbytes - 1] = '\0';
132
133 volatile int c __attribute__((unused)) = 0;
134 while (state.KeepRunning()) {
135 c += __strlen_chk(bmstrlenAligned, __builtin_object_size(bmstrlenAligned, 0));
136 }
137 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
138 }
139 #endif
140
141 // Specifies the maximum number of copies to replicate
Bm_function_Stpncpy(benchmark::State & state)142 static void Bm_function_Stpncpy(benchmark::State &state)
143 {
144 const size_t nbytes = state.range(0);
145 const size_t limitsize = state.range(1);
146 const size_t srcAlignment = state.range(2);
147 const size_t dstAlignment = state.range(2);
148
149 vector<char> src;
150 vector<char> dst;
151 char *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, 'z');
152 char *dstAligned = GetAlignedPtr(&dst, dstAlignment, nbytes);
153 srcAligned[nbytes - 1] = '\0';
154
155 while (state.KeepRunning()) {
156 stpncpy(dstAligned, srcAligned, limitsize);
157 }
158 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
159 }
160
161 // Used to copy one string to another, you can limit the maximum length of copying
Bm_function_Strncpy(benchmark::State & state)162 static void Bm_function_Strncpy(benchmark::State &state)
163 {
164 const size_t nbytes = state.range(0);
165 const size_t limitsize = state.range(1);
166 const size_t srcAlignment = state.range(2);
167 const size_t dstAlignment = state.range(2);
168
169 vector<char> src;
170 vector<char> dst;
171 char *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, 'z');
172 char *dstAligned = GetAlignedPtr(&dst, dstAlignment, nbytes);
173 srcAligned[nbytes - 1] = '\0';
174
175 while (state.KeepRunning()) {
176 strncpy(dstAligned, srcAligned, limitsize);
177 }
178 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
179 }
180
181 // Comparing whether two binary blocks of data are equal is functionally similar to MEMCMP
Bm_function_Bcmp(benchmark::State & state)182 static void Bm_function_Bcmp(benchmark::State &state)
183 {
184 const size_t nbytes = state.range(0);
185 const size_t srcAlignment = state.range(1);
186 const size_t dstAlignment = state.range(2);
187
188 vector<char> src;
189 vector<char> dst;
190 char *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, 'x');
191 char *dstAligned = GetAlignedPtrFilled(&dst, dstAlignment, nbytes, 'x');
192
193 volatile int c __attribute__((unused)) = 0;
194 while (state.KeepRunning()) {
195 c += bcmp(dstAligned, srcAligned, nbytes);
196 }
197 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
198 }
199
200 // Find the first character in a given string that matches any character in another specified string
Bm_function_Strpbrk(benchmark::State & state)201 static void Bm_function_Strpbrk(benchmark::State &state)
202 {
203 const char *strpbrktestsrc[] = { "method", "setTimeout", "open.harmony",
204 "libfilemgmt_libhilog", "libwallpaperextension",
205 "startup", "libwallpapermanager", "param_trie" };
206 const char *strpbrktesttag[] = { "th", "me", "enh", "lo", "en", "tu", "ag", "pa" };
207 const char *src = strpbrktestsrc[state.range(0)];
208 const char *tag = strpbrktesttag[state.range(0)];
209 for (auto _ : state) {
210 benchmark::DoNotOptimize(strpbrk(src, tag));
211 }
212 }
213
214 // Set the first n characters in the wide string to another wide character
Bm_function_Wmemset(benchmark::State & state)215 static void Bm_function_Wmemset(benchmark::State &state)
216 {
217 const size_t nbytes = state.range(0);
218 const size_t alignment = state.range(1);
219
220 vector<wchar_t> buf;
221 wchar_t *bufAligned = GetAlignedPtr(&buf, alignment, nbytes + 1);
222
223 while (state.KeepRunning()) {
224 wmemset(bufAligned, L'n', nbytes);
225 }
226 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
227 }
228
229 // The first n characters in the source memory region are copied to the destination memory region
Bm_function_Wmemcpy(benchmark::State & state)230 static void Bm_function_Wmemcpy(benchmark::State &state)
231 {
232 const size_t nbytes = state.range(0);
233 const size_t srcAlignment = state.range(1);
234 const size_t dstAlignment = state.range(2);
235
236 vector<wchar_t> src;
237 vector<wchar_t> dst;
238 wchar_t *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, L'z');
239 wchar_t *dstAligned = GetAlignedPtr(&dst, dstAlignment, nbytes);
240 while (state.KeepRunning()) {
241 wmemcpy(dstAligned, srcAligned, nbytes);
242 }
243 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
244 }
245
246 // Returns the index value of the first successful match
Bm_function_Strcspn(benchmark::State & state)247 static void Bm_function_Strcspn(benchmark::State &state)
248 {
249 const char *strcspnsrc[] = { "system/lib64", "system/lib64/chipset-pub-sdk", "vendor/lib64/chipsetsdk",
250 "system/lib64/ndk", "system/lib64/platformsdk", "system/lib64/priv-platformsdk",
251 "system/lib64/module/data", "tem/lib64/module/security" };
252 const char *strcspntag[] = { "vendor/lib64", "/system/lib64/chipset-sdk", "/system/lib64/ndk",
253 "lib64/chipset-pub-sdk", "priv-platformsdk", "/system/lib64/priv-module",
254 "/system/lib64/module/multimedia", "/system/lib" };
255 const char *src = strcspnsrc[state.range(0)];
256 const char *tag = strcspntag[state.range(0)];
257 for (auto _ : state) {
258 benchmark::DoNotOptimize(strcspn(src, tag));
259 }
260 }
261
262 #if not defined __APPLE__
Bm_function_Strchrnul_exist(benchmark::State & state)263 static void Bm_function_Strchrnul_exist(benchmark::State &state)
264 {
265 const char *str = "musl.ld.debug.dlclose";
266 int c = 46;
267 for (auto _ : state) {
268 benchmark::DoNotOptimize(strchrnul(str, c));
269 }
270 }
271
Bm_function_Strchrnul_noexist(benchmark::State & state)272 static void Bm_function_Strchrnul_noexist(benchmark::State &state)
273 {
274 const char *str = "all";
275 int c = 46;
276 for (auto _ : state) {
277 benchmark::DoNotOptimize(strchrnul(str, c));
278 }
279 }
280
Bm_function_Strchrnul(benchmark::State & state)281 static void Bm_function_Strchrnul(benchmark::State &state)
282 {
283 const size_t nbytes = state.range(0);
284 const size_t haystackAlignment = state.range(1);
285 std::vector<char> haystack;
286 char *haystackAligned = GetAlignedPtrFilled(&haystack, haystackAlignment, nbytes, 'x');
287 haystackAligned[nbytes - 1] = '\0';
288
289 while (state.KeepRunning()) {
290 strchrnul(haystackAligned, '.');
291 }
292 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
293 }
294 #endif
295
Bm_function_Strcasecmp_capital_equal(benchmark::State & state)296 static void Bm_function_Strcasecmp_capital_equal(benchmark::State &state)
297 {
298 const char *l = "ABCDEF";
299 const char *r = "ABCDEF";
300 for (auto _ : state) {
301 benchmark::DoNotOptimize(strcasecmp(l, r));
302 }
303 }
304
Bm_function_Strcasecmp_small_equal(benchmark::State & state)305 static void Bm_function_Strcasecmp_small_equal(benchmark::State &state)
306 {
307 const char *l = "abcdef";
308 const char *r = "abcdef";
309 for (auto _ : state) {
310 benchmark::DoNotOptimize(strcasecmp(l, r));
311 }
312 }
313
Bm_function_Strcasecmp_equal(benchmark::State & state)314 static void Bm_function_Strcasecmp_equal(benchmark::State &state)
315 {
316 const char *l = "aBcDeD";
317 const char *r = "ABCdEd";
318 for (auto _ : state) {
319 benchmark::DoNotOptimize(strcasecmp(l, r));
320 }
321 }
322
Bm_function_Strcasecmp_not_equal(benchmark::State & state)323 static void Bm_function_Strcasecmp_not_equal(benchmark::State &state)
324 {
325 const char *l = "bbcdef";
326 const char *r = "bBCdEd";
327 for (auto _ : state) {
328 benchmark::DoNotOptimize(strcasecmp(l, r));
329 }
330 }
331
Bm_function_Strcasecmp(benchmark::State & state)332 static void Bm_function_Strcasecmp(benchmark::State &state)
333 {
334 const size_t nbytes = state.range(0);
335 const size_t haystackAlignment = state.range(1);
336 const size_t needleAlignment = state.range(2);
337
338 std::vector<char> haystack;
339 std::vector<char> needle;
340 char *haystackAligned = GetAlignedPtrFilled(&haystack, haystackAlignment, nbytes, 'x');
341 char *needleAligned = GetAlignedPtrFilled(&needle, needleAlignment, nbytes, 'x');
342
343 for (auto _ : state) {
344 benchmark::DoNotOptimize(strcasecmp(haystackAligned, needleAligned));
345 }
346 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
347 }
348
Bm_function_Strncasecmp(benchmark::State & state)349 static void Bm_function_Strncasecmp(benchmark::State &state)
350 {
351 const size_t nbytes = state.range(0);
352 const size_t haystackAlignment = state.range(1);
353 const size_t needleAlignment = state.range(2);
354
355 std::vector<char> haystack;
356 std::vector<char> needle;
357 char *haystackAligned = GetAlignedPtrFilled(&haystack, haystackAlignment, nbytes, 'x');
358 char *needleAligned = GetAlignedPtrFilled(&needle, needleAlignment, nbytes, 'x');
359 for (auto _ : state) {
360 benchmark::DoNotOptimize(strncasecmp(haystackAligned, needleAligned, nbytes));
361 }
362 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
363 }
364
Bm_function_Strdup(benchmark::State & state)365 static void Bm_function_Strdup(benchmark::State &state)
366 {
367 const size_t nbytes = state.range(0);
368 const size_t haystackAlignment = state.range(1);
369 std::vector<char> haystack;
370 char *haystackAligned = GetAlignedPtrFilled(&haystack, haystackAlignment, nbytes, 'x');
371 haystackAligned[nbytes - 1] = '\0';
372 char* ptr = nullptr;
373 while (state.KeepRunning()) {
374 benchmark::DoNotOptimize(ptr = strdup(haystackAligned));
375 free(ptr);
376 }
377 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
378 }
379
Bm_function_Strncat(benchmark::State & state)380 static void Bm_function_Strncat(benchmark::State &state)
381 {
382 const size_t nbytes = state.range(0);
383 const size_t haystackAlignment = state.range(1);
384 std::vector<char> haystack;
385 char *haystackAligned = GetAlignedPtrFilled(&haystack, haystackAlignment, nbytes, 'x');
386 haystackAligned[nbytes - 1] = '\0';
387 std::vector<char> dstStack;
388 char *dst = GetAlignedPtrFilled(&dstStack, haystackAlignment, nbytes, '0');
389 while (state.KeepRunning()) {
390 dst[0] = 0;
391 benchmark::DoNotOptimize(strncat(dst, haystackAligned, nbytes));
392 }
393 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
394 }
395
396 // Compare two wide strings according to the current local environment
BM_function_Wcscoll(benchmark::State & state)397 static void BM_function_Wcscoll(benchmark::State& state)
398 {
399 setlocale(LC_ALL, "");
400 const size_t nbytes = state.range(0);
401 const size_t srcAlignment = state.range(1);
402 const size_t dstAlignment = state.range(2);
403
404 vector<wchar_t> src;
405 vector<wchar_t> dst;
406 wchar_t* srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, L'n');
407 wchar_t* dstAligned = GetAlignedPtrFilled(&dst, dstAlignment, nbytes, L'z');
408
409 volatile int c __attribute__((unused)) = 0;
410 while (state.KeepRunning()) {
411 c += wcscoll(dstAligned, srcAligned);
412 }
413 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
414 }
415
416 // Similar to wcscoll the main difference is its support for localization
BM_function_Wcscoll_l(benchmark::State & state)417 static void BM_function_Wcscoll_l(benchmark::State& state)
418 {
419 setlocale(LC_ALL, "");
420 locale_t loc = newlocale(LC_ALL_MASK, "", nullptr);
421 const size_t nbytes = state.range(0);
422 const size_t srcAlignment = state.range(1);
423 const size_t dstAlignment = state.range(2);
424
425 vector<wchar_t> src;
426 vector<wchar_t> dst;
427 wchar_t* srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, L'n');
428 wchar_t* dstAligned = GetAlignedPtrFilled(&dst, dstAlignment, nbytes, L'z');
429
430 volatile int c __attribute__((unused)) = 0;
431 while (state.KeepRunning()) {
432 c += wcscoll_l(dstAligned, srcAligned, loc);
433 }
434 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
435 }
436
437 // Converts wide characters to single bytes
Bm_function_Wctob(benchmark::State & state)438 static void Bm_function_Wctob(benchmark::State &state)
439 {
440 setlocale(LC_ALL, "");
441 const wchar_t test [] = { L'Y', L'd', L'M', L'O', L'K', L'J', L'L', L's', L'\0' };
442 const wchar_t a = test[state.range(0)];
443 for (auto _ : state) {
444 benchmark::DoNotOptimize(wctob(a));
445 }
446 }
447
448 // Converts single-byte characters to wide characters
Bm_function_Btowc(benchmark::State & state)449 static void Bm_function_Btowc(benchmark::State &state)
450 {
451 setlocale(LC_ALL, "");
452 const char c [] = { 't', 'h', 'i', 's', 'a', 'm', 'z', 'g', '\0'};
453 const char a = c[state.range(0)];
454 for (auto _ : state) {
455 benchmark::DoNotOptimize(btowc(a));
456 }
457 }
458
459 // According to the program's current regional options the character set converts
460 // the first n characters of the string src and places them in the string dest
Bm_function_Strxfrm(benchmark::State & state)461 static void Bm_function_Strxfrm(benchmark::State &state)
462 {
463 const size_t nbytes = state.range(0);
464 const size_t srcAlignment = state.range(1);
465 const size_t dstAlignment = state.range(2);
466
467 vector<char> src;
468 vector<char> dst;
469 char *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, 'z');
470 char *dstAligned = GetAlignedPtr(&dst, dstAlignment, nbytes);
471 srcAligned[nbytes - 1] = '\0';
472
473 while (state.KeepRunning()) {
474 strxfrm(dstAligned, srcAligned, nbytes);
475 }
476 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
477 }
478
479 // Similar to strxfrm the main difference is its support for localization
Bm_function_Strxfrm_l(benchmark::State & state)480 static void Bm_function_Strxfrm_l(benchmark::State &state)
481 {
482 setlocale(LC_ALL, "");
483 locale_t loc = newlocale(LC_ALL_MASK, "", nullptr);
484 const size_t nbytes = state.range(0);
485 const size_t srcAlignment = state.range(1);
486 const size_t dstAlignment = state.range(2);
487
488 vector<char> src;
489 vector<char> dst;
490 char *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, 'z');
491 char *dstAligned = GetAlignedPtr(&dst, dstAlignment, nbytes);
492 srcAligned[nbytes - 1] = '\0';
493
494 while (state.KeepRunning()) {
495 strxfrm_l(dstAligned, srcAligned, nbytes, loc);
496 }
497 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
498 }
499
500 // Converts a wide-character string into a sequenced string
501 // according to specified localization rules
Bm_function_Wcsxfrm(benchmark::State & state)502 static void Bm_function_Wcsxfrm(benchmark::State &state)
503 {
504 setlocale(LC_ALL, "");
505 const size_t nbytes = state.range(0);
506 const size_t srcAlignment = state.range(1);
507 const size_t dstAlignment = state.range(2);
508
509 vector<wchar_t> src;
510 vector<wchar_t> dst;
511 wchar_t *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, L'A');
512 wchar_t *dstAligned = GetAlignedPtr(&dst, dstAlignment, nbytes);
513 srcAligned[nbytes - 1] = '\0';
514
515 while (state.KeepRunning()) {
516 wcsxfrm(dstAligned, srcAligned, nbytes);
517 }
518 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
519 }
520
521 // Similar to wcsxfrm the main difference is its support for localization
Bm_function_Wcsxfrm_l(benchmark::State & state)522 static void Bm_function_Wcsxfrm_l(benchmark::State &state)
523 {
524 setlocale(LC_ALL, "");
525 locale_t loc = newlocale(LC_ALL_MASK, "", nullptr);
526 const size_t nbytes = state.range(0);
527 const size_t srcAlignment = state.range(1);
528 const size_t dstAlignment = state.range(2);
529
530 vector<wchar_t> src;
531 vector<wchar_t> dst;
532 wchar_t *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, L'A');
533 wchar_t *dstAligned = GetAlignedPtr(&dst, dstAlignment, nbytes);
534 srcAligned[nbytes - 1] = '\0';
535
536 while (state.KeepRunning()) {
537 wcsxfrm_l(dstAligned, srcAligned, nbytes, loc);
538 }
539 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
540 }
541
542 // compare two strings according to localized language rules
BM_function_Strcoll(benchmark::State & state)543 static void BM_function_Strcoll(benchmark::State& state)
544 {
545 setlocale(LC_ALL, "");
546 const size_t nbytes = state.range(0);
547 const size_t s1Alignment = state.range(1);
548 const size_t s2Alignment = state.range(2);
549
550 vector<char> s1;
551 vector<char> s2;
552 char* s1ALigned = GetAlignedPtrFilled(&s1, s1Alignment, nbytes, 'x');
553 char* s2ALigned = GetAlignedPtrFilled(&s2, s2Alignment, nbytes, 'x');
554 s1ALigned[nbytes - 1] = '\0';
555 s2ALigned[nbytes - 1] = '\0';
556
557 volatile int c __attribute__((unused));
558 while (state.KeepRunning()) {
559 c = strcoll(s1ALigned, s2ALigned);
560 }
561 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
562 }
563
564 // Similar to strcoll the main difference is its support for localization
BM_function_Strcoll_l(benchmark::State & state)565 static void BM_function_Strcoll_l(benchmark::State& state)
566 {
567 setlocale(LC_ALL, "");
568 locale_t loc = newlocale(LC_ALL_MASK, "", nullptr);
569 const size_t nbytes = state.range(0);
570 const size_t s1Alignment = state.range(1);
571 const size_t s2Alignment = state.range(2);
572
573 vector<char> s1;
574 vector<char> s2;
575 char* s1ALigned = GetAlignedPtrFilled(&s1, s1Alignment, nbytes, 'x');
576 char* s2ALigned = GetAlignedPtrFilled(&s2, s2Alignment, nbytes, 'x');
577 s1ALigned[nbytes - 1] = '\0';
578 s2ALigned[nbytes - 1] = '\0';
579
580 volatile int c __attribute__((unused));
581 while (state.KeepRunning()) {
582 c = strcoll_l(s1ALigned, s2ALigned, loc);
583 }
584 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
585 }
586
Bm_function_Wmemcmp(benchmark::State & state)587 static void Bm_function_Wmemcmp(benchmark::State &state)
588 {
589 const size_t nbytes = state.range(0);
590 const size_t srcAlignment = state.range(1);
591 const size_t dstAlignment = state.range(2);
592
593 vector<wchar_t> src;
594 vector<wchar_t> dst;
595 wchar_t *srcAligned = GetAlignedPtrFilled(&src, srcAlignment, nbytes, 'x');
596 wchar_t *dstAligned = GetAlignedPtrFilled(&dst, dstAlignment, nbytes, 'x');
597
598 while (state.KeepRunning()) {
599 benchmark::DoNotOptimize(wmemcmp(dstAligned, srcAligned, nbytes));
600 }
601 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
602 }
603
BM_function_Wcsstr(benchmark::State & state)604 static void BM_function_Wcsstr(benchmark::State& state)
605 {
606 const size_t nbytes = state.range(0);
607 const size_t haystack_alignment = state.range(1);
608 const size_t needle_alignment = state.range(2);
609
610 std::vector<wchar_t> haystack;
611 std::vector<wchar_t> needle;
612 wchar_t* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, L'x');
613 wchar_t* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment,
614 std::min(nbytes, static_cast<size_t>(5)), L'x');
615
616 if (nbytes / 4 > 2) {
617 for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) {
618 haystack_aligned[4 * i + 3] = L'y';
619 }
620 }
621 haystack_aligned[nbytes - 1] = L'\0';
622 needle_aligned[needle.size() - 1] = L'\0';
623
624 while (state.KeepRunning()) {
625 if (wcsstr(haystack_aligned, needle_aligned) == nullptr) {
626 errx(1, "ERROR: strstr failed to find valid substring.");
627 }
628 }
629 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
630 }
631
BM_function_Strcasestr(benchmark::State & state)632 static void BM_function_Strcasestr(benchmark::State& state)
633 {
634 const size_t nbytes = state.range(0);
635 const size_t haystack_alignment = state.range(1);
636 const size_t needle_alignment = state.range(2);
637
638 std::vector<char> haystack;
639 std::vector<char> needle;
640 char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
641 char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment,
642 std::min(nbytes, static_cast<size_t>(5)), 'X');
643 if (nbytes / 4 > 2) {
644 for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) {
645 haystack_aligned[4 * i + 3] = 'y';
646 }
647 }
648 haystack_aligned[nbytes - 1] = '\0';
649 needle_aligned[needle.size() - 1] = '\0';
650
651 while (state.KeepRunning()) {
652 if (strcasestr(haystack_aligned, needle_aligned) == nullptr) {
653 errx(1, "ERROR: strcasestr failed to find valid substring.");
654 }
655 }
656 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
657 }
658
BM_function_Strlcat(benchmark::State & state)659 static void BM_function_Strlcat(benchmark::State& state)
660 {
661 const size_t nbytes = state.range(0);
662 const size_t needle_alignment = state.range(1);
663
664 std::vector<char> haystack(nbytes);
665 std::vector<char> needle;
666 char* dstBuf = haystack.data();
667 char* srcBuf = GetAlignedPtrFilled(&needle, needle_alignment, nbytes, 'x');
668 srcBuf[needle.size() - 1] = '\0';
669
670 while (state.KeepRunning()) {
671 benchmark::DoNotOptimize(strlcat(dstBuf, srcBuf, nbytes));
672 }
673 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
674 }
675
BM_function_Getdelim(benchmark::State & state)676 static void BM_function_Getdelim(benchmark::State& state)
677 {
678 FILE* fp = fopen(DATA_ROOT"/data/getdlim.txt", "w+");
679 if (fp == nullptr) {
680 errx(1, "ERROR: fp is nullptr\n");
681 }
682 const char* buf = "123 4567 78901 ";
683 const int bufLen = strlen(buf);
684 const int repeatTimes = 1024 * 1024;
685 //增大测试文件,确保在进行benchmark循环测试时,不会读到文件尾而进入fseek函数影响数据准确性
686 for (int i = 0; i < repeatTimes; ++i) {
687 fwrite(buf, bufLen, 1, fp);
688 }
689
690 fflush(fp);
691 fseek(fp, 0, SEEK_SET);
692
693 size_t maxReadLen = 1024;
694 char* readBuf = (char*)malloc(maxReadLen);
695 if (readBuf == nullptr) {
696 errx(1, "ERROR: readBuf is nullptr\n");
697 }
698
699 while (state.KeepRunning()) {
700 ssize_t n = getdelim(&readBuf, &maxReadLen, ' ', fp);
701 if (n == -1) {
702 fseek(fp, 0, SEEK_SET);
703 }
704 }
705 free(readBuf);
706 fclose(fp);
707 }
708 MUSL_BENCHMARK(BM_function_Getdelim);
709 MUSL_BENCHMARK_WITH_ARG(BM_function_Strlcat, "ALIGNED_ONEBUF");
710 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Memchr, StringtestArgs);
711 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Strnlen, StringtestArgs);
712 #if not defined __APPLE__
713 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strlen_chk, "BENCHMARK_8");
714 #endif
715 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Stpncpy, StringtestArgs);
716 MUSL_BENCHMARK_WITH_APPLY(Bm_function_Strncpy, StringtestArgs);
717 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strcspn, "BENCHMARK_8");
718 #if not defined __APPLE__
719 MUSL_BENCHMARK(Bm_function_Strchrnul_exist);
720 MUSL_BENCHMARK(Bm_function_Strchrnul_noexist);
721 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strchrnul, "ALIGNED_ONEBUF");
722 #endif
723 MUSL_BENCHMARK(Bm_function_Strcasecmp_capital_equal);
724 MUSL_BENCHMARK(Bm_function_Strcasecmp_small_equal);
725 MUSL_BENCHMARK(Bm_function_Strcasecmp_equal);
726 MUSL_BENCHMARK(Bm_function_Strcasecmp_not_equal);
727 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strcasecmp, "ALIGNED_TWOBUF");
728 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strncasecmp, "ALIGNED_TWOBUF");
729 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strrchr, "BENCHMARK_8");
730 MUSL_BENCHMARK_WITH_ARG(Bm_function_Bcmp, "ALIGNED_TWOBUF");
731 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strpbrk, "BENCHMARK_8");
732 MUSL_BENCHMARK_WITH_ARG(Bm_function_Wmemset, "ALIGNED_ONEBUF");
733 MUSL_BENCHMARK_WITH_ARG(Bm_function_Wmemcpy, "ALIGNED_TWOBUF");
734 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strdup, "ALIGNED_ONEBUF");
735 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strncat, "ALIGNED_ONEBUF");
736 MUSL_BENCHMARK_WITH_ARG(BM_function_Wcscoll, "ALIGNED_TWOBUF");
737 MUSL_BENCHMARK_WITH_ARG(BM_function_Wcscoll_l, "ALIGNED_TWOBUF");
738 MUSL_BENCHMARK_WITH_ARG(Bm_function_Wctob, "BENCHMARK_8");
739 MUSL_BENCHMARK_WITH_ARG(Bm_function_Btowc, "BENCHMARK_8");
740 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strxfrm, "ALIGNED_TWOBUF");
741 MUSL_BENCHMARK_WITH_ARG(Bm_function_Strxfrm_l, "ALIGNED_TWOBUF");
742 MUSL_BENCHMARK_WITH_ARG(Bm_function_Wcsxfrm, "ALIGNED_TWOBUF");
743 MUSL_BENCHMARK_WITH_ARG(Bm_function_Wcsxfrm_l, "ALIGNED_TWOBUF");
744 MUSL_BENCHMARK_WITH_ARG(BM_function_Strcoll, "ALIGNED_TWOBUF");
745 MUSL_BENCHMARK_WITH_ARG(BM_function_Strcoll_l, "ALIGNED_TWOBUF");
746 MUSL_BENCHMARK_WITH_ARG(Bm_function_Wmemcmp, "ALIGNED_TWOBUF");
747 MUSL_BENCHMARK_WITH_ARG(BM_function_Wcsstr, "ALIGNED_TWOBUF");
748 MUSL_BENCHMARK_WITH_ARG(BM_function_Strcasestr, "ALIGNED_TWOBUF");
749