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