• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ************************************************************************
3 * Copyright (c) 1997-2006, International Business Machines
4 * Corporation and others.  All Rights Reserved.
5 ************************************************************************
6 */
7 
8 #ifndef _UTIMER_H
9 #define _UTIMER_H
10 
11 #include "unicode/utypes.h"
12 
13 #if defined(U_WINDOWS)
14 #   define VC_EXTRALEAN
15 #   define WIN32_LEAN_AND_MEAN
16 #   include <windows.h>
17 #else
18 #   include <time.h>
19 #   include <sys/time.h>
20 #   include <unistd.h>
21 #endif
22 
23 /**
24  * This API provides functions for performing performance measurement
25  * There are 3 main usage scenarios.
26  * i) Loop until a threshold time is reached:
27  *    Example:
28  *    <code>
29  *      typedef Params Params;
30  *      struct Params{
31  *          UChar* target;
32  *          int32_t targetLen;
33  *          const UChar* source;
34  *          int32_t sourceLen;
35  *          UNormalizationMode mode;
36  *      }
37  *      void NormFn( void* param){
38  *          Params* parameters = ( Params*) param;
39  *          UErrorCode error = U_ZERO_ERROR;
40  *          unorm_normalize(parameters->source, parameters->sourceLen, parameters->mode, 0, parameters->target, parameters->targetLen, &error);
41  *          if(U_FAILURE(error)){
42  *              printf("Normalization failed\n");
43  *          }
44  *      }
45  *
46  *      int main(){
47  *          // time the normalization function
48  *          double timeTaken = 0;
49  *          Params param;
50  *          param.source  // set up the source buffer
51  *          param.target   // set up the target buffer
52  *          .... so on ...
53  *          UTimer timer;
54  *          // time the loop for 10 seconds at least and find out the loop count and time taken
55  *          timeTaken = utimer_loopUntilDone((double)10,(void*) param, NormFn, &loopCount);
56  *      }
57  *     </code>
58  *
59  * ii) Measure the time taken
60  *     Example:
61  *     <code>
62  *      double perfNormalization(NormFn fn,const char* mode,Line* fileLines,int32_t loopCount){
63  *          int  line;
64  *          int  loops;
65  *          UErrorCode error = U_ZERO_ERROR;
66  *          UChar* dest=NULL;
67  *          int32_t destCapacity=0;
68  *          int len =-1;
69  *          double elapsedTime = 0;
70  *          int retVal=0;
71  *
72  *          UChar arr[5000];
73  *          dest=arr;
74  *          destCapacity = 5000;
75  *          UTimer start;
76  *
77  *          // Initialize cache and ensure the data is loaded.
78  *          // This loop checks for errors in Normalization. Once we pass the initialization
79  *          // without errors we can safelly assume that there are no errors while timing the
80  *          // funtion
81  *          for (loops=0; loops<10; loops++) {
82  *              for (line=0; line < gNumFileLines; line++) {
83  *                  if (opt_uselen) {
84  *                      len = fileLines[line].len;
85  *                  }
86  *
87  *                  retVal= fn(fileLines[line].name,len,dest,destCapacity,&error);
88  *      #if defined(U_WINDOWS)
89  *                  if(retVal==0 ){
90  *                      fprintf(stderr,"Normalization of string in Windows API failed for mode %s. ErrorNo: %i at line number %i\n",mode,GetLastError(),line);
91  *                      return 0;
92  *                  }
93  *      #endif
94  *                  if(U_FAILURE(error)){
95  *                      fprintf(stderr,"Normalization of string in ICU API failed for mode %s. Error: %s at line number %i\n",mode,u_errorName(error),line);
96  *                      return 0;
97  *                  }
98  *
99  *              }
100  *          }
101  *
102  *          //compute the time
103  *
104  *          utimer_getTime(&start);
105  *          for (loops=0; loops<loopCount; loops++) {
106  *              for (line=0; line < gNumFileLines; line++) {
107  *                  if (opt_uselen) {
108  *                      len = fileLines[line].len;
109  *                  }
110  *
111  *                  retVal= fn(fileLines[line].name,len,dest,destCapacity,&error);
112  *
113  *              }
114  *          }
115  *
116  *          return utimer_getElapsedSeconds(&start);
117  *      }
118  *      </code>
119  *
120  * iii) Let a higher level function do the calculation of confidence levels etc.
121  *     Example:
122  *     <code>
123  *       void perf(UTimer* timer, UChar* source, int32_t sourceLen, UChar* target, int32_t targetLen, int32_t loopCount,UNormalizationMode mode, UErrorCode* error){
124  *              int32_t loops;
125  *              for (loops=0; loops<loopCount; loops++) {
126  *                  unorm_normalize(source,sourceLen,target, targetLen,mode,error);
127  *              }
128  *              utimer_getTime(timer);
129  *       }
130  *       void main(const char* argsc, int argv){
131  *          // read the file and setup the data
132  *          // set up options
133  *          UTimer start,timer1, timer2, timer3, timer4;
134  *          double NFDTimeTaken, NFCTimeTaken, FCDTimeTaken;
135  *          switch(opt){
136  *              case 0:
137  *                  utimer_getTime(start);
138  *                  perf(timer1, source,sourceLen, target, targetLen,loopCount,UNORM_NFD,&error);
139  *                  NFDTimeTaken = utimer_getDeltaSeconds(start,timer1);
140  *              case 1:
141  *                  timer_getTime(start);
142  *                  perf(timer2,source,sourceLen,target,targetLen,loopCount,UNORM_NFC,&error);
143  *                  NFCTimeTaken = utimer_getDeltaSeconds(start,timer2);
144  *                  perf(timer3, source, sourceLen, target,targetLen, loopCount, UNORM_FCD,&error);
145  *              // ........so on .............
146  *           }
147  *          // calculate confidence levels etc and print
148  *
149  *       }
150  *
151  *     </code>
152  *
153  */
154 
155 typedef struct UTimer UTimer;
156 
157 typedef void FuntionToBeTimed(void* param);
158 
159 
160 #if defined(U_WINDOWS)
161 
162     struct UTimer{
163         LARGE_INTEGER start;
164         LARGE_INTEGER placeHolder;
165     };
166 
uprv_initFrequency(UTimer * timer)167     int uprv_initFrequency(UTimer* timer)
168     {
169         return QueryPerformanceFrequency(&timer->placeHolder);
170     }
uprv_start(UTimer * timer)171     void uprv_start(UTimer* timer)
172     {
173         QueryPerformanceCounter(&timer->start);
174     }
uprv_delta(UTimer * timer1,UTimer * timer2)175     double uprv_delta(UTimer* timer1, UTimer* timer2){
176         return ((double)(timer2->start.QuadPart - timer1->start.QuadPart))/((double)timer1->placeHolder.QuadPart);
177     }
uprv_compareFrequency(UTimer * timer1,UTimer * timer2)178     UBool uprv_compareFrequency(UTimer* timer1, UTimer* timer2){
179         return (timer1->placeHolder.QuadPart == timer2->placeHolder.QuadPart);
180     }
181 
182 #else
183 
184     struct UTimer{
185         struct timeval start;
186         struct timeval placeHolder;
187     };
188 
uprv_initFrequency(UTimer *)189     int32_t uprv_initFrequency(UTimer* /*timer*/)
190     {
191         return 0;
192     }
uprv_start(UTimer * timer)193     void uprv_start(UTimer* timer)
194     {
195         gettimeofday(&timer->start, 0);
196     }
uprv_delta(UTimer * timer1,UTimer * timer2)197     double uprv_delta(UTimer* timer1, UTimer* timer2){
198         double t1, t2;
199 
200         t1 =  (double)timer1->start.tv_sec + (double)timer1->start.tv_usec/(1000*1000);
201         t2 =  (double)timer2->start.tv_sec + (double)timer2->start.tv_usec/(1000*1000);
202         return (t2-t1);
203     }
uprv_compareFrequency(UTimer *,UTimer *)204     UBool uprv_compareFrequency(UTimer* /*timer1*/, UTimer* /*timer2*/){
205         return TRUE;
206     }
207 
208 #endif
209 /**
210  * Intializes the timer with the current time
211  *
212  * @param timer A pointer to UTimer struct to recieve the current time
213  */
214 static U_INLINE void U_EXPORT2
utimer_getTime(UTimer * timer)215 utimer_getTime(UTimer* timer){
216     uprv_initFrequency(timer);
217     uprv_start(timer);
218 }
219 
220 /**
221  * Returns the difference in times between timer1 and timer2 by subtracting
222  * timer1's time from timer2's time
223  *
224  * @param timer1 A pointer to UTimer struct to be used as starting time
225  * @param timer2 A pointer to UTimer struct to be used as end time
226  * @return Time in seconds
227  */
228 static U_INLINE double U_EXPORT2
utimer_getDeltaSeconds(UTimer * timer1,UTimer * timer2)229 utimer_getDeltaSeconds(UTimer* timer1, UTimer* timer2){
230     if(uprv_compareFrequency(timer1,timer2)){
231         return uprv_delta(timer1,timer2);
232     }
233     /* got error return -1 */
234     return -1;
235 }
236 
237 /**
238  * Returns the time elapsed from the starting time represented by the
239  * UTimer struct pointer passed
240  * @param timer A pointer to UTimer struct to be used as starting time
241  * @return Time elapsed in seconds
242  */
243 static U_INLINE double U_EXPORT2
utimer_getElapsedSeconds(UTimer * timer)244 utimer_getElapsedSeconds(UTimer* timer){
245     UTimer temp;
246     utimer_getTime(&temp);
247     return uprv_delta(timer,&temp);
248 }
249 
250 /**
251  * Executes the function pointed to for a given time and returns exact time
252  * taken and number of iterations of the loop
253  * @param thresholTimeVal
254  * @param loopCount output param to recieve the number of iterations
255  * @param fn    The funtion to be executed
256  * @param param Parameters to be passed to the fn
257  * @return the time elapsed in seconds
258  */
259 static U_INLINE double U_EXPORT2
utimer_loopUntilDone(double thresholdTimeVal,int32_t * loopCount,FuntionToBeTimed fn,void * param)260 utimer_loopUntilDone(double thresholdTimeVal,
261                      int32_t* loopCount,
262                      FuntionToBeTimed fn,
263                      void* param){
264     UTimer timer;
265     double currentVal=0;
266     *loopCount = 0;
267     utimer_getTime(&timer);
268     for(;currentVal<thresholdTimeVal;){
269         fn(param);
270         currentVal = utimer_getElapsedSeconds(&timer);
271         *loopCount++;
272     }
273     return currentVal;
274 }
275 
276 #endif
277 
278