• 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 #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