Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : *
3 : : * Copyright (C) 2010 Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General Public
18 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include <string.h>
22 : :
23 : : #include <glib.h>
24 : :
25 : : static guint num_iterations = 0;
26 : :
27 : : static const char str_ascii[] =
28 : : "The quick brown fox jumps over the lazy dog";
29 : :
30 : : static const gchar str_latin1[] =
31 : : "Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich";
32 : :
33 : : /* Energizing GOELRO-talk in Russian, used by KDE */
34 : : static const char str_cyrillic[] =
35 : : "Широкая электрификация южных губерний даст мощный толчок подъёму "
36 : : "сельского хозяйства.";
37 : :
38 : : /* First sentence from the Wikipedia article:
39 : : * http://zh.wikipedia.org/w/index.php?title=%E6%B1%89%E5%AD%97&oldid=13053137 */
40 : : static const char str_han[] =
41 : : "漢字,亦稱中文字、中国字,在台灣又被稱為國字,是漢字文化圈廣泛使用的一種文字,屬於表意文字的詞素音節文字";
42 : :
43 : : typedef int (* GrindFunc) (const char *, gsize);
44 : :
45 : : #define GRIND_LOOP_BEGIN \
46 : : { \
47 : : guint i; \
48 : : for (i = 0; i < num_iterations; i++)
49 : :
50 : : #define GRIND_LOOP_END \
51 : : }
52 : :
53 : : static int
54 : 4 : grind_get_char (const char *str, gsize len)
55 : : {
56 : 4 : gunichar acc = 0;
57 [ + + ]: 8 : GRIND_LOOP_BEGIN
58 : : {
59 : 4 : const char *p = str;
60 [ + + ]: 247 : while (*p)
61 : : {
62 : 243 : acc += g_utf8_get_char (p);
63 : 243 : p = g_utf8_next_char (p);
64 : : }
65 : : }
66 : : GRIND_LOOP_END;
67 : 4 : return acc;
68 : : }
69 : :
70 : : static int
71 : 4 : grind_get_char_validated (const char *str, gsize len)
72 : : {
73 : 4 : gunichar acc = 0;
74 [ + + ]: 8 : GRIND_LOOP_BEGIN
75 : : {
76 : 4 : const char *p = str;
77 [ + + ]: 247 : while (*p)
78 : : {
79 : 243 : acc += g_utf8_get_char_validated (p, -1);
80 : 243 : p = g_utf8_next_char (p);
81 : : }
82 : : }
83 : : GRIND_LOOP_END;
84 : 4 : return acc;
85 : : }
86 : :
87 : : static int
88 : 4 : grind_utf8_to_ucs4 (const char *str, gsize len)
89 : : {
90 [ + + ]: 8 : GRIND_LOOP_BEGIN
91 : : {
92 : : gunichar *ustr;
93 : 4 : ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL);
94 : 4 : g_free (ustr);
95 : : }
96 : : GRIND_LOOP_END;
97 : 4 : return 0;
98 : : }
99 : :
100 : : static int
101 : 4 : grind_get_char_backwards (const char *str, gsize len)
102 : : {
103 : 4 : gunichar acc = 0;
104 [ + + ]: 8 : GRIND_LOOP_BEGIN
105 : : {
106 : 4 : const char *p = str + len;
107 : : do
108 : : {
109 : 243 : p = g_utf8_prev_char (p);
110 : 243 : acc += g_utf8_get_char (p);
111 : : }
112 [ + + ]: 243 : while (p != str);
113 : : }
114 : : GRIND_LOOP_END;
115 : 4 : return acc;
116 : : }
117 : :
118 : : static int
119 : 4 : grind_utf8_to_ucs4_sized (const char *str, gsize len)
120 : : {
121 [ + + ]: 8 : GRIND_LOOP_BEGIN
122 : : {
123 : : gunichar *ustr;
124 : 4 : ustr = g_utf8_to_ucs4 (str, len, NULL, NULL, NULL);
125 : 4 : g_free (ustr);
126 : : }
127 : : GRIND_LOOP_END;
128 : 4 : return 0;
129 : : }
130 : :
131 : : static int
132 : 4 : grind_utf8_to_ucs4_fast (const char *str, gsize len)
133 : : {
134 [ + + ]: 8 : GRIND_LOOP_BEGIN
135 : : {
136 : : gunichar *ustr;
137 : 4 : ustr = g_utf8_to_ucs4_fast (str, -1, NULL);
138 : 4 : g_free (ustr);
139 : : }
140 : : GRIND_LOOP_END;
141 : 4 : return 0;
142 : : }
143 : :
144 : : static int
145 : 4 : grind_utf8_to_ucs4_fast_sized (const char *str, gsize len)
146 : : {
147 [ + + ]: 8 : GRIND_LOOP_BEGIN
148 : : {
149 : : gunichar *ustr;
150 : 4 : ustr = g_utf8_to_ucs4_fast (str, len, NULL);
151 : 4 : g_free (ustr);
152 : : }
153 : : GRIND_LOOP_END;
154 : 4 : return 0;
155 : : }
156 : :
157 : : static int
158 : 4 : grind_utf8_validate (const char *str, gsize len)
159 : : {
160 [ + + ]: 8 : GRIND_LOOP_BEGIN
161 : 4 : g_utf8_validate (str, -1, NULL);
162 : : GRIND_LOOP_END;
163 : 4 : return 0;
164 : : }
165 : :
166 : : static int
167 : 4 : grind_utf8_validate_sized (const char *str, gsize len)
168 : : {
169 [ + + ]: 8 : GRIND_LOOP_BEGIN
170 : 4 : g_utf8_validate (str, len, NULL);
171 : : GRIND_LOOP_END;
172 : 4 : return 0;
173 : : }
174 : :
175 : : typedef struct _GrindData {
176 : : GrindFunc func;
177 : : const char *str;
178 : : } GrindData;
179 : :
180 : : static void
181 : 36 : perform (gconstpointer data)
182 : : {
183 : 36 : GrindData *gd = (GrindData *) data;
184 : 36 : GrindFunc grind_func = gd->func;
185 : 36 : const char *str = gd->str;
186 : : gsize len;
187 : : gulong bytes_ground;
188 : : gdouble time_elapsed;
189 : : gdouble result;
190 : :
191 : 36 : len = strlen (str);
192 : 36 : bytes_ground = (gulong) len * num_iterations;
193 : :
194 : 36 : g_test_timer_start ();
195 : :
196 : 36 : grind_func (str, len);
197 : :
198 : 36 : time_elapsed = g_test_timer_elapsed ();
199 : :
200 : 36 : result = ((gdouble) bytes_ground / time_elapsed) * 1.0e-6;
201 : :
202 : 36 : g_test_maximized_result (result, "%7.1f MB/s", result);
203 : :
204 : 36 : g_slice_free (GrindData, gd);
205 : 36 : }
206 : :
207 : : static void
208 : 9 : add_cases(const char *path, GrindFunc func)
209 : : {
210 : : #define ADD_CASE(script) \
211 : : G_STMT_START { \
212 : : GrindData *gd; \
213 : : gchar *full_path; \
214 : : gd = g_slice_new0(GrindData); \
215 : : gd->func = func; \
216 : : gd->str = str_##script; \
217 : : full_path = g_strdup_printf("%s/" #script, path); \
218 : : g_test_add_data_func (full_path, gd, perform); \
219 : : g_free (full_path); \
220 : : } G_STMT_END
221 : :
222 : 9 : ADD_CASE(ascii);
223 : 9 : ADD_CASE(latin1);
224 : 9 : ADD_CASE(cyrillic);
225 : 9 : ADD_CASE(han);
226 : :
227 : : #undef ADD_CASE
228 : 9 : }
229 : :
230 : : int
231 : 1 : main (int argc, char **argv)
232 : : {
233 : 1 : g_test_init (&argc, &argv, NULL);
234 : :
235 [ - + ]: 1 : num_iterations = g_test_perf () ? 500000 : 1;
236 : :
237 : 1 : add_cases ("/utf8/perf/get_char", grind_get_char);
238 : 1 : add_cases ("/utf8/perf/get_char-backwards", grind_get_char_backwards);
239 : 1 : add_cases ("/utf8/perf/get_char_validated", grind_get_char_validated);
240 : 1 : add_cases ("/utf8/perf/utf8_to_ucs4", grind_utf8_to_ucs4);
241 : 1 : add_cases ("/utf8/perf/utf8_to_ucs4-sized", grind_utf8_to_ucs4_sized);
242 : 1 : add_cases ("/utf8/perf/utf8_to_ucs4_fast", grind_utf8_to_ucs4_fast);
243 : 1 : add_cases ("/utf8/perf/utf8_to_ucs4_fast-sized", grind_utf8_to_ucs4_fast_sized);
244 : 1 : add_cases ("/utf8/perf/utf8_validate", grind_utf8_validate);
245 : 1 : add_cases ("/utf8/perf/utf8_validate-sized", grind_utf8_validate_sized);
246 : :
247 : 1 : return g_test_run ();
248 : : }
|