1 /* Benchmark mcel and some alternatives
2 Copyright 2023-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
26 #include "bench-multibyte.h"
33 typedef unsigned long long (*test_function
) (char const *, char const *, int);
35 static unsigned long long
36 noop_test (char const *text
, char const *text_end
, int repeat
)
38 unsigned long long sum
= 0;
40 for (int count
= 0; count
< repeat
; count
++)
43 for (iter
= text
; iter
< text_end
; iter
++)
44 sum
+= (uintptr_t) iter
;
50 static unsigned long long
51 single_test (char const *text
, char const *text_end
, int repeat
)
53 unsigned long long sum
= 0;
55 for (int count
= 0; count
< repeat
; count
++)
56 for (char const *iter
= text
; iter
< text_end
; )
58 unsigned char c
= *iter
++;
65 static unsigned long long
66 mbiter_test (char const *text
, char const *text_end
, int repeat
)
68 unsigned long long sum
= 0;
70 size_t text_len
= text_end
- text
;
71 for (int count
= 0; count
< repeat
; count
++)
74 for (mbi_init (iter
, text
, text_len
); mbi_avail (iter
); )
76 mbchar_t cur
= mbi_cur (iter
);
78 sum
+= cur
.wc_valid
? cur
.wc
: (unsigned char) *mb_ptr (cur
) << 16;
85 static unsigned long long
86 mbiterf_test (char const *text
, char const *text_end
, int repeat
)
88 unsigned long long sum
= 0;
90 for (int count
= 0; count
< repeat
; count
++)
94 for (mbif_init (state
), iter
= text
; mbif_avail (state
, iter
, text_end
); )
96 mbchar_t cur
= mbif_next (state
, iter
, text_end
);
98 sum
+= cur
.wc_valid
? cur
.wc
: (unsigned char) *mb_ptr (cur
) << 16;
105 static unsigned long long
106 mbuiter_test (char const *text
, char const *text_end
, int repeat
)
108 unsigned long long sum
= 0;
110 for (int count
= 0; count
< repeat
; count
++)
111 for (char const *t
= text
; t
< text_end
; t
++)
113 mbui_iterator_t iter
;
114 for (mbui_init (iter
, t
); mbui_avail (iter
); )
116 mbchar_t cur
= mbui_cur (iter
);
118 sum
+= cur
.wc_valid
? cur
.wc
: (unsigned char) *mb_ptr (cur
) << 16;
120 t
= mbui_cur_ptr (iter
);
126 static unsigned long long
127 mbuiterf_test (char const *text
, _GL_UNUSED
char const *text_end
, int repeat
)
129 unsigned long long sum
= 0;
131 for (int count
= 0; count
< repeat
; count
++)
132 for (char const *t
= text
; t
< text_end
; t
++)
136 for (mbuif_init (state
), iter
= t
; mbuif_avail (state
, iter
); )
138 mbchar_t cur
= mbuif_next (state
, iter
);
139 iter
+= mb_len (cur
);
140 sum
+= cur
.wc_valid
? cur
.wc
: (unsigned char) *mb_ptr (cur
) << 16;
148 static unsigned long long
149 mcel_test (char const *text
, char const *text_end
, int repeat
)
151 unsigned long long sum
= 0;
153 for (int count
= 0; count
< repeat
; count
++)
154 for (char const *iter
= text
; iter
< text_end
; )
156 mcel_t g
= mcel_scan (iter
, text_end
);
158 sum
+= g
.ch
| (g
.err
<< 16);
164 static unsigned long long
165 mcuel_test (char const *text
, char const *text_end
, int repeat
)
167 unsigned long long sum
= 0;
169 for (int count
= 0; count
< repeat
; count
++)
170 for (char const *t
= text
; t
< text_end
; t
++)
172 char const *iter
= t
;
175 mcel_t g
= mcel_scanz (iter
);
177 sum
+= g
.ch
| (g
.err
<< 16);
185 static unsigned long long
186 do_1_test (test_function test
, char const *text
,
187 char const *text_end
, int repeat
, struct timings_state
*ts
)
190 unsigned long long sum
= test (text
, text_end
, repeat
);
196 do_test (char test
, int repeat
, char const *locale_name
,
197 char const *text
, size_t text_len
)
199 if (setlocale (LC_ALL
, locale_name
) != NULL
)
201 char const *text_end
= text
+ text_len
;
207 struct timings_state ts
;
208 unsigned long long volatile sum
;
210 { "noop", noop_test
},
211 { "single", single_test
},
212 { "mbiter", mbiter_test
},
213 { "mbiterf", mbiterf_test
},
214 { "mbuiter", mbuiter_test
},
215 { "mbuiterf", mbuiterf_test
},
216 { "mcel", mcel_test
},
217 { "mcuel", mcuel_test
},
219 int ntestdesc
= sizeof testdesc
/ sizeof *testdesc
;
220 for (int i
= 0; i
< ntestdesc
; i
++)
222 do_1_test (testdesc
[i
].fn
, text
, text_end
, repeat
, &testdesc
[i
].ts
);
224 setlocale (LC_ALL
, "C");
226 static bool header_printed
;
230 for (int i
= 0; i
< ntestdesc
; i
++)
231 printf (" %8s", testdesc
[i
].name
);
233 header_printed
= true;
237 for (int i
= 0; i
< ntestdesc
; i
++)
239 double user_usec
= testdesc
[i
].ts
.user_usec
;
240 double sys_usec
= testdesc
[i
].ts
.sys_usec
;
241 printf (" %8.3f", (user_usec
+ sys_usec
) / 1e6
);
247 printf ("Skipping test: locale %s not installed.\n", locale_name
);
251 /* Performs some or all of the following tests:
252 A - ASCII text, C locale
253 B - ASCII text, UTF-8 locale
254 C - French text, C locale
255 D - French text, ISO-8859-1 locale
256 E - French text, UTF-8 locale
257 F - Greek text, C locale
258 G - Greek text, ISO-8859-7 locale
259 H - Greek text, UTF-8 locale
260 I - Chinese text, UTF-8 locale
261 J - Chinese text, GB18030 locale
262 K - Random bytes, C locale
263 L - Random bytes, UTF-8 locale
264 a - short ASCII text, C locale
265 b - short ASCII text, UTF-8 locale
266 e - short French text, UTF-8 locale
267 h - short Greek text, UTF-8 locale
268 i - short Chinese text, UTF-8 locale
269 Pass the tests to be performed as first argument. */
271 main (int argc
, char *argv
[])
275 fprintf (stderr
, "Usage: %s TESTS REPETITIONS\n", argv
[0]);
277 fprintf (stderr
, "Example: %s ABCDEFGHIJKLabehi 100000\n", argv
[0]);
281 char const *tests
= argv
[1];
282 int repeat
= atoi (argv
[2]);
286 /* Execute each test. */
288 for (i
= 0; i
< strlen (tests
); i
++)
290 char test
= tests
[i
];
295 do_test (test
, repeat
, "C", text_latin_ascii
,
296 strlen (text_latin_ascii
));
299 do_test (test
, repeat
, "C", TEXT_LATIN_ASCII_LINE1
,
300 strlen (TEXT_LATIN_ASCII_LINE1
));
303 do_test (test
, repeat
, "en_US.UTF-8", text_latin_ascii
,
304 strlen (text_latin_ascii
));
307 do_test (test
, repeat
, "en_US.UTF-8", TEXT_LATIN_ASCII_LINE1
,
308 strlen (TEXT_LATIN_ASCII_LINE1
));
311 do_test (test
, repeat
, "C", text_french_iso8859
,
312 strlen (text_french_iso8859
));
315 do_test (test
, repeat
, "fr_FR.ISO-8859-1", text_french_iso8859
,
316 strlen (text_french_iso8859
));
319 do_test (test
, repeat
, "en_US.UTF-8", text_french_utf8
,
320 strlen (text_french_utf8
));
323 do_test (test
, repeat
, "en_US.UTF-8", TEXT_FRENCH_UTF8_LINE1
,
324 strlen (TEXT_FRENCH_UTF8_LINE1
));
327 do_test (test
, repeat
, "C", text_greek_iso8859
,
328 strlen (text_greek_iso8859
));
331 do_test (test
, repeat
, "el_GR.ISO-8859-7", text_greek_iso8859
,
332 strlen (text_greek_iso8859
));
335 do_test (test
, repeat
, "en_US.UTF-8", text_greek_utf8
,
336 strlen (text_greek_utf8
));
339 do_test (test
, repeat
, "en_US.UTF-8", TEXT_GREEK_UTF8_LINE1
,
340 strlen (TEXT_GREEK_UTF8_LINE1
));
343 do_test (test
, repeat
, "en_US.UTF-8", text_chinese_utf8
,
344 strlen (text_chinese_utf8
));
347 do_test (test
, repeat
, "en_US.UTF-8", TEXT_CHINESE_UTF8_LINE1
,
348 strlen (TEXT_CHINESE_UTF8_LINE1
));
351 do_test (test
, repeat
, "zh_CN.GB18030", text_chinese_gb18030
,
352 strlen (text_chinese_gb18030
));
355 do_test (test
, repeat
, "C", text_random_bytes
,
356 sizeof text_random_bytes
- 1);
359 do_test (test
, repeat
, "en_US.UTF-8", text_random_bytes
,
360 sizeof text_random_bytes
- 1);