53eeaf1ea1a0244cd3b7f4a83ed27cbed7f4e86b
[platform/upstream/fribidi.git] / fribidi-benchmark.c
1 /* FriBidi
2  * fribidi-benchmark.c - command line benchmark tool for libfribidi
3  *
4  * $Id: fribidi-benchmark.c,v 1.8 2009-04-14 03:49:52 behdad Exp $
5  * $Author: behdad $
6  * $Date: 2009-04-14 03:49:52 $
7  * $Revision: 1.8 $
8  * $Source: /home/behdad/src/fdo/fribidi/togit/git/../fribidi/fribidi2/bin/fribidi-benchmark.c,v $
9  *
10  * Authors:
11  *   Behdad Esfahbod, 2001, 2002, 2004
12  *   Dov Grobgeld, 1999, 2000
13  *
14  * Copyright (C) 2004 Sharif FarsiWeb, Inc
15  * Copyright (C) 2001,2002 Behdad Esfahbod
16  * Copyright (C) 1999,2000 Dov Grobgeld
17  * 
18  * This library is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU Lesser General Public
20  * License as published by the Free Software Foundation; either
21  * version 2.1 of the License, or (at your option) any later version.
22  * 
23  * This library is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * Lesser General Public License for more details.
27  * 
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with this library, in a file named COPYING; if not, write to the
30  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
31  * Boston, MA 02110-1301, USA
32  * 
33  * For licensing issues, contact <license@farsiweb.info>.
34  */
35
36 #include <common.h>
37
38 #include <fribidi.h>
39
40 #include <stdio.h>
41 #if STDC_HEADERS+0
42 # include <stdlib.h>
43 # include <stddef.h>
44 #else
45 # if HAVE_STDLIB_H
46 #  include <stdlib.h>
47 # endif
48 #endif
49 #if HAVE_STRING_H+0
50 # if !STDC_HEADERS && HAVE_MEMORY_H
51 #  include <memory.h>
52 # endif
53 # include <string.h>
54 #endif
55 #if HAVE_STRINGS_H+0
56 # include <strings.h>
57 #endif
58 #if HAVE_SYS_TIMES_H+0
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
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
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
116 version (
117   void
118 )
119 {
120   printf (appname " %s", fribidi_version_info);
121   exit (0);
122 }
123
124 static double
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 #if HAVE_SYS_TIMES_H+0
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
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       if (!fribidi_log2vis (us, len, &base,
222                             /* output */
223                             out_us, positionVtoL, positionLtoV,
224                             embedding_list))
225         die2
226           ("something failed in fribidi_log2vis.\n"
227            "perhaps memory allocation failure.", NULL);
228     }
229
230   /* stop timer */
231   time1 = utime ();
232
233   /* output result */
234   printf ("Length = %d\n", len);
235   printf ("Iterations = %d\n", niter);
236   printf ("%d len*iterations in %f seconds\n", len * niter, time1 - time0);
237   printf ("= %.0f kilo.length.iterations/second\n",
238           1.0 * len * niter / 1000 / (time1 - time0));
239
240   return;
241 }
242
243 int
244 main (
245   int argc,
246   char *argv[]
247 )
248 {
249   int niter = NUM_ITER;
250
251   /* Parse the command line */
252   argv[0] = appname;
253   while (1)
254     {
255       int option_index = 0, c;
256       static struct option long_options[] = {
257         {"help", 0, 0, 'h'},
258         {"version", 0, 0, 'V'},
259         {"niter", 0, 0, 'n'},
260         {0, 0, 0, 0}
261       };
262
263       c = getopt_long (argc, argv, "hVn:", long_options, &option_index);
264       if (c == -1)
265         break;
266
267       switch (c)
268         {
269         case 0:
270           break;
271         case 'h':
272           help ();
273           break;
274         case 'V':
275           version ();
276           break;
277         case 'n':
278           niter = atoi (optarg);
279           if (niter <= 0)
280             die2 ("invalid number of iterations `%s'\n", optarg);
281           break;
282         case ':':
283         case '?':
284           die2 (NULL, NULL);
285           break;
286         default:
287           break;
288         }
289     }
290
291   printf ("* Without explicit marks:\n");
292   benchmark (TEST_STRING, niter);
293   printf ("\n");
294   printf ("* With explicit marks:\n");
295   benchmark (TEST_STRING_EXPLICIT, niter);
296
297   return 0;
298 }
299
300 /* Editor directions:
301  * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
302  */