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