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