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 281