1 /* Measure strlen functions.
2    Copyright (C) 2013-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #define TEST_MAIN
20 #ifndef WIDE
21 # define TEST_NAME "strnlen"
22 #else
23 # define TEST_NAME "wcsnlen"
24 # define generic_strnlen generic_wcsnlen
25 # define memchr_strnlen wcschr_wcsnlen
26 #endif /* WIDE */
27 #include "bench-string.h"
28 #include "json-lib.h"
29 
30 #define BIG_CHAR MAX_CHAR
31 
32 #ifndef WIDE
33 # define MIDDLE_CHAR 127
34 #else
35 # define MIDDLE_CHAR 1121
36 #endif /* WIDE */
37 
38 typedef size_t (*proto_t) (const CHAR *, size_t);
39 size_t generic_strnlen (const CHAR *, size_t);
40 
41 size_t
memchr_strnlen(const CHAR * s,size_t maxlen)42 memchr_strnlen (const CHAR *s, size_t maxlen)
43 {
44   const CHAR *s1 = MEMCHR (s, 0, maxlen);
45   return (s1 == NULL) ? maxlen : s1 - s;
46 }
47 
48 IMPL (STRNLEN, 1)
49 IMPL (memchr_strnlen, 0)
50 IMPL (generic_strnlen, 0)
51 
52 static void
do_one_test(json_ctx_t * json_ctx,impl_t * impl,const CHAR * s,size_t maxlen,size_t exp_len)53 do_one_test (json_ctx_t *json_ctx, impl_t *impl, const CHAR *s, size_t maxlen,
54 	     size_t exp_len)
55 {
56   size_t len = CALL (impl, s, maxlen), i, iters = INNER_LOOP_ITERS_LARGE;
57   timing_t start, stop, cur;
58 
59   if (len != exp_len)
60     {
61       error (0, 0, "Wrong result in function %s %zd %zd", impl->name, len,
62 	     exp_len);
63       ret = 1;
64       return;
65     }
66 
67   TIMING_NOW (start);
68   for (i = 0; i < iters; ++i)
69     {
70       CALL (impl, s, maxlen);
71     }
72   TIMING_NOW (stop);
73 
74   TIMING_DIFF (cur, start, stop);
75 
76   json_element_double (json_ctx, (double) cur / (double) iters);
77 }
78 
79 static void
do_test(json_ctx_t * json_ctx,size_t align,size_t len,size_t maxlen,int max_char)80 do_test (json_ctx_t *json_ctx, size_t align, size_t len, size_t maxlen,
81 	 int max_char)
82 {
83   size_t i;
84 
85   align &= getpagesize () - 1;
86   if ((align + len) * sizeof (CHAR) >= page_size)
87     return;
88 
89   CHAR *buf = (CHAR *) (buf1);
90 
91   json_element_object_begin (json_ctx);
92   json_attr_uint (json_ctx, "len", len);
93   json_attr_uint (json_ctx, "maxlen", maxlen);
94   json_attr_uint (json_ctx, "max_char", max_char);
95   json_attr_uint (json_ctx, "align", align);
96   json_array_begin (json_ctx, "timings");
97 
98   for (i = 0; i < len; ++i)
99     buf[align + i] = 1 + 7 * i % max_char;
100   buf[align + len] = 0;
101 
102   FOR_EACH_IMPL (impl, 0)
103     do_one_test (json_ctx, impl, (CHAR *) (buf + align), maxlen,
104 		 MIN (len, maxlen));
105 
106   json_array_end (json_ctx);
107   json_element_object_end (json_ctx);
108 }
109 
110 int
test_main(void)111 test_main (void)
112 {
113   size_t i;
114   json_ctx_t json_ctx;
115 
116   test_init ();
117 
118   json_init (&json_ctx, 0, stdout);
119 
120   json_document_begin (&json_ctx);
121   json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
122 
123   json_attr_object_begin (&json_ctx, "functions");
124   json_attr_object_begin (&json_ctx, TEST_NAME);
125   json_attr_string (&json_ctx, "bench-variant", "");
126 
127   json_array_begin (&json_ctx, "ifuncs");
128   FOR_EACH_IMPL (impl, 0)
129     json_element_string (&json_ctx, impl->name);
130   json_array_end (&json_ctx);
131 
132   json_array_begin (&json_ctx, "results");
133 
134   for (i = 1; i < 8; ++i)
135     {
136       do_test (&json_ctx, 0, i, i - 1, MIDDLE_CHAR);
137       do_test (&json_ctx, 0, i, i, MIDDLE_CHAR);
138       do_test (&json_ctx, 0, i, i + 1, MIDDLE_CHAR);
139     }
140 
141   for (i = 1; i < 8; ++i)
142     {
143       do_test (&json_ctx, i, i, i - 1, MIDDLE_CHAR);
144       do_test (&json_ctx, i, i, i, MIDDLE_CHAR);
145       do_test (&json_ctx, i, i, i + 1, MIDDLE_CHAR);
146     }
147 
148   for (i = 2; i <= 10; ++i)
149     {
150       do_test (&json_ctx, 0, 1 << i, 5000, MIDDLE_CHAR);
151       do_test (&json_ctx, 1, 1 << i, 5000, MIDDLE_CHAR);
152     }
153 
154   for (i = 1; i < 8; ++i)
155     do_test (&json_ctx, 0, i, 5000, BIG_CHAR);
156 
157   for (i = 1; i < 8; ++i)
158     do_test (&json_ctx, i, i, 5000, BIG_CHAR);
159 
160   for (i = 2; i <= 10; ++i)
161     {
162       do_test (&json_ctx, 0, 1 << i, 5000, BIG_CHAR);
163       do_test (&json_ctx, 1, 1 << i, 5000, BIG_CHAR);
164     }
165 
166   json_array_end (&json_ctx);
167   json_attr_object_end (&json_ctx);
168   json_attr_object_end (&json_ctx);
169   json_document_end (&json_ctx);
170 
171   return ret;
172 }
173 
174 #include <support/test-driver.c>
175 
176 #define libc_hidden_def(X)
177 #ifndef WIDE
178 # undef STRNLEN
179 # define STRNLEN generic_strnlen
180 # include <string/strnlen.c>
181 #else
182 # define WCSNLEN generic_strnlen
183 # include <wcsmbs/wcsnlen.c>
184 #endif
185