1 /* FriBidi
2 * fribidi-benchmark.c - command line benchmark tool for libfribidi
3 *
4 * Authors:
5 * Behdad Esfahbod, 2001, 2002, 2004
6 * Dov Grobgeld, 1999, 2000
7 *
8 * Copyright (C) 2004 Sharif FarsiWeb, Inc
9 * Copyright (C) 2001,2002 Behdad Esfahbod
10 * Copyright (C) 1999,2000 Dov Grobgeld
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this library, in a file named COPYING; if not, write to the
24 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA
26 *
27 * For licensing issues, contact <fribidi.license@gmail.com>.
28 */
29
30 #include <common.h>
31
32 #include <fribidi.h>
33 #include <fribidi-deprecated.h>
34
35 #include <stdio.h>
36
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
40
41 #ifdef STDC_HEADERS
42 # include <stdlib.h>
43 # include <stddef.h>
44 #else
45 # if HAVE_STDLIB_H
46 # include <stdlib.h>
47 # endif
48 #endif
49 #ifdef HAVE_STRING_H
50 # if !STDC_HEADERS && HAVE_MEMORY_H
51 # include <memory.h>
52 # endif
53 # include <string.h>
54 #endif
55 #ifdef HAVE_STRINGS_H
56 # include <strings.h>
57 #endif
58 #ifdef HAVE_SYS_TIMES_H
59 # include <sys/times.h>
60 #endif
61 #ifdef _WIN32
62 #include <windows.h>
63 #endif /* _WIN32 */
64
65 #include "getopt.h"
66
67 #define appname "fribidi_benchmark"
68
69 #define MAX_STR_LEN 1000
70 #define NUM_ITER 2000
71
72 static void
die2(const char * fmt,const char * arg)73 die2 (
74 const char *fmt,
75 const char *arg
76 )
77 {
78 fprintf (stderr, "%s: ", appname);
79 if (fmt)
80 fprintf (stderr, fmt, arg);
81 fprintf (stderr, "Try `%s --help' for more information.\n", appname);
82 exit (-1);
83 }
84
85 #define TEST_STRING \
86 "a THE QUICK -123,456 (FOX JUMPS ) DOG the quick !1@7#4&5^ over the dog " \
87 "123,456 OVER THE 5%+ 4.0 LAZY"
88 #define TEST_STRING_EXPLICIT \
89 "this is _LJUST_o a _lsimple _Rte%ST_o th_oat HAS A _LPDF missing" \
90 "AnD hOw_L AbOuT, 123,987 tHiS_o a GO_oOD - _L_oTE_oST. " \
91 "here_L is_o_o_o _R a good one_o And _r 123,987_LT_oHE_R next_o oNE:" \
92 "_R_r and the last _LONE_o IS THE _rbest _lONE and" \
93 "a _L_L_L_LL_L_L_L_L_L_L_L_L_Rbug_o_o_o_o_o_o" \
94 "_R_r and the last _LONE_o IS THE _rbest _lONE and" \
95 "A REAL BIG_l_o BUG! _L _l_r_R_L_laslaj siw_o_Rlkj sslk" \
96 "a _L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_Rbug" \
97 "here_L is_o_o_o _R ab one_o _r 123,987_LT_oHE_R t_o oNE:" \
98
99 static void
help(void)100 help (
101 void
102 )
103 {
104 printf
105 ("Usage: " appname " [OPTION]...\n"
106 "A program for benchmarking the speed of the " FRIBIDI_NAME
107 " library.\n" "\n"
108 " -h, --help Display this information and exit\n"
109 " -V, --version Display version information and exit\n"
110 " -n, --niter N Number of iterations. Default is %d.\n"
111 "\nReport bugs online at\n<" FRIBIDI_BUGREPORT ">.\n", NUM_ITER);
112 exit (0);
113 }
114
115 static void
version(void)116 version (
117 void
118 )
119 {
120 printf (appname " %s", fribidi_version_info);
121 exit (0);
122 }
123
124 static double
utime(void)125 utime (
126 void
127 )
128 {
129 #ifdef _WIN32
130 FILETIME creationTime, exitTime, kernelTime, userTime;
131 HANDLE currentProcess = GetCurrentProcess();
132 if (GetProcessTimes(currentProcess, &creationTime, &exitTime, &kernelTime, &userTime))
133 {
134 unsigned __int64 myTime = userTime.dwHighDateTime;
135 myTime = (myTime << 32) | userTime.dwLowDateTime;
136 return 1e-7 * myTime;
137 }
138 else
139 return 0.0;
140 #else /* !_WIN32 */
141 #ifdef HAVE_SYS_TIMES_H
142 struct tms tb;
143 times (&tb);
144 return 0.01 * tb.tms_utime;
145 #else
146 #warning Please fill in here to use other functions for determining time.
147 return 0.0;
148 #endif
149 #endif
150 }
151
152 static void
benchmark(const char * S_,int niter)153 benchmark (
154 const char *S_,
155 int niter
156 )
157 {
158 int len, i;
159 FriBidiChar us[MAX_STR_LEN], out_us[MAX_STR_LEN];
160 FriBidiStrIndex positionLtoV[MAX_STR_LEN], positionVtoL[MAX_STR_LEN];
161 FriBidiLevel embedding_list[MAX_STR_LEN];
162 FriBidiParType base;
163 double time0, time1;
164
165 {
166 int j;
167 len = strlen (S_);
168 for (i = 0, j = 0; i < len; i++)
169 {
170 if (S_[i] == '_')
171 switch (S_[++i])
172 {
173 case '>':
174 us[j++] = FRIBIDI_CHAR_LRM;
175 break;
176 case '<':
177 us[j++] = FRIBIDI_CHAR_RLM;
178 break;
179 case 'l':
180 us[j++] = FRIBIDI_CHAR_LRE;
181 break;
182 case 'r':
183 us[j++] = FRIBIDI_CHAR_RLE;
184 break;
185 case 'L':
186 us[j++] = FRIBIDI_CHAR_LRO;
187 break;
188 case 'R':
189 us[j++] = FRIBIDI_CHAR_RLO;
190 break;
191 case 'o':
192 us[j++] = FRIBIDI_CHAR_PDF;
193 break;
194 case '_':
195 us[j++] = '_';
196 break;
197 default:
198 us[j++] = '_';
199 i--;
200 break;
201 }
202 else
203 us[j++] = S_[i];
204 if (us[j] >= 'A' && us[j] <= 'F')
205 us[j] += FRIBIDI_CHAR_ARABIC_ALEF - 'A';
206 else if (us[j] >= 'G' && us[j] <= 'Z')
207 us[j] += FRIBIDI_CHAR_HEBREW_ALEF - 'G';
208 else if (us[j] >= '6' && us[j] <= '9')
209 us[j] += FRIBIDI_CHAR_ARABIC_ZERO - '0';
210 }
211 len = j;
212 }
213
214 /* Start timer */
215 time0 = utime ();
216
217 for (i = 0; i < niter; i++)
218 {
219 /* Create a bidi string */
220 base = FRIBIDI_PAR_ON;
221 FRIBIDI_BEGIN_IGNORE_DEPRECATIONS
222 if (!fribidi_log2vis (us, len, &base,
223 /* output */
224 out_us, positionVtoL, positionLtoV,
225 embedding_list))
226 die2
227 ("something failed in fribidi_log2vis.\n"
228 "perhaps memory allocation failure.", NULL);
229 FRIBIDI_END_IGNORE_DEPRECATIONS
230 }
231
232 /* stop timer */
233 time1 = utime ();
234
235 /* output result */
236 printf ("Length = %d\n", len);
237 printf ("Iterations = %d\n", niter);
238 printf ("%d len*iterations in %f seconds\n", len * niter, time1 - time0);
239 printf ("= %.0f kilo.length.iterations/second\n",
240 1.0 * len * niter / 1000 / (time1 - time0));
241
242 return;
243 }
244
245 int
main(int argc,char * argv[])246 main (
247 int argc,
248 char *argv[]
249 )
250 {
251 int niter = NUM_ITER;
252
253 /* Parse the command line */
254 argv[0] = appname;
255 while (1)
256 {
257 int option_index = 0, c;
258 static struct option long_options[] = {
259 {"help", 0, 0, 'h'},
260 {"version", 0, 0, 'V'},
261 {"niter", 0, 0, 'n'},
262 {0, 0, 0, 0}
263 };
264
265 c = getopt_long (argc, argv, "hVn:", long_options, &option_index);
266 if (c == -1)
267 break;
268
269 switch (c)
270 {
271 case 0:
272 break;
273 case 'h':
274 help ();
275 break;
276 case 'V':
277 version ();
278 break;
279 case 'n':
280 niter = atoi (optarg);
281 if (niter <= 0)
282 die2 ("invalid number of iterations `%s'\n", optarg);
283 break;
284 case ':':
285 case '?':
286 die2 (NULL, NULL);
287 break;
288 default:
289 break;
290 }
291 }
292
293 printf ("* Without explicit marks:\n");
294 benchmark (TEST_STRING, niter);
295 printf ("\n");
296 printf ("* With explicit marks:\n");
297 benchmark (TEST_STRING_EXPLICIT, niter);
298
299 return 0;
300 }
301
302 /* Editor directions:
303 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
304 */
305