12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci/* 42e5b6d6dSopenharmony_ci************************************************************************ 52e5b6d6dSopenharmony_ci* Copyright (c) 1997-2012, International Business Machines 62e5b6d6dSopenharmony_ci* Corporation and others. All Rights Reserved. 72e5b6d6dSopenharmony_ci************************************************************************ 82e5b6d6dSopenharmony_ci*/ 92e5b6d6dSopenharmony_ci 102e5b6d6dSopenharmony_ci#ifndef _UTIMER_H 112e5b6d6dSopenharmony_ci#define _UTIMER_H 122e5b6d6dSopenharmony_ci 132e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 142e5b6d6dSopenharmony_ci 152e5b6d6dSopenharmony_ci#if U_PLATFORM_USES_ONLY_WIN32_API 162e5b6d6dSopenharmony_ci# define VC_EXTRALEAN 172e5b6d6dSopenharmony_ci# define WIN32_LEAN_AND_MEAN 182e5b6d6dSopenharmony_ci# include <windows.h> 192e5b6d6dSopenharmony_ci#else 202e5b6d6dSopenharmony_ci# if U_PLATFORM == U_PF_OS390 && !defined(__UU) 212e5b6d6dSopenharmony_ci# define __UU /* Universal Unix - for struct timeval */ 222e5b6d6dSopenharmony_ci# endif 232e5b6d6dSopenharmony_ci# include <time.h> 242e5b6d6dSopenharmony_ci# include <sys/time.h> 252e5b6d6dSopenharmony_ci# include <unistd.h> 262e5b6d6dSopenharmony_ci#endif 272e5b6d6dSopenharmony_ci 282e5b6d6dSopenharmony_ci/** 292e5b6d6dSopenharmony_ci * This API provides functions for performing performance measurement 302e5b6d6dSopenharmony_ci * There are 3 main usage scenarios. 312e5b6d6dSopenharmony_ci * i) Loop until a threshold time is reached: 322e5b6d6dSopenharmony_ci * Example: 332e5b6d6dSopenharmony_ci * <code> 342e5b6d6dSopenharmony_ci * typedef Params Params; 352e5b6d6dSopenharmony_ci * struct Params{ 362e5b6d6dSopenharmony_ci * UChar* target; 372e5b6d6dSopenharmony_ci * int32_t targetLen; 382e5b6d6dSopenharmony_ci * const UChar* source; 392e5b6d6dSopenharmony_ci * int32_t sourceLen; 402e5b6d6dSopenharmony_ci * UNormalizationMode mode; 412e5b6d6dSopenharmony_ci * } 422e5b6d6dSopenharmony_ci * void NormFn( void* param){ 432e5b6d6dSopenharmony_ci * Params* parameters = ( Params*) param; 442e5b6d6dSopenharmony_ci * UErrorCode error = U_ZERO_ERROR; 452e5b6d6dSopenharmony_ci * unorm_normalize(parameters->source, parameters->sourceLen, parameters->mode, 0, parameters->target, parameters->targetLen, &error); 462e5b6d6dSopenharmony_ci * if(U_FAILURE(error)){ 472e5b6d6dSopenharmony_ci * printf("Normalization failed\n"); 482e5b6d6dSopenharmony_ci * } 492e5b6d6dSopenharmony_ci * } 502e5b6d6dSopenharmony_ci * 512e5b6d6dSopenharmony_ci * int main(){ 522e5b6d6dSopenharmony_ci * // time the normalization function 532e5b6d6dSopenharmony_ci * double timeTaken = 0; 542e5b6d6dSopenharmony_ci * Params param; 552e5b6d6dSopenharmony_ci * param.source // set up the source buffer 562e5b6d6dSopenharmony_ci * param.target // set up the target buffer 572e5b6d6dSopenharmony_ci * .... so on ... 582e5b6d6dSopenharmony_ci * UTimer timer; 592e5b6d6dSopenharmony_ci * // time the loop for 10 seconds at least and find out the loop count and time taken 602e5b6d6dSopenharmony_ci * timeTaken = utimer_loopUntilDone((double)10,(void*) param, NormFn, &loopCount); 612e5b6d6dSopenharmony_ci * } 622e5b6d6dSopenharmony_ci * </code> 632e5b6d6dSopenharmony_ci * 642e5b6d6dSopenharmony_ci * ii) Measure the time taken 652e5b6d6dSopenharmony_ci * Example: 662e5b6d6dSopenharmony_ci * <code> 672e5b6d6dSopenharmony_ci * double perfNormalization(NormFn fn,const char* mode,Line* fileLines,int32_t loopCount){ 682e5b6d6dSopenharmony_ci * int line; 692e5b6d6dSopenharmony_ci * int loops; 702e5b6d6dSopenharmony_ci * UErrorCode error = U_ZERO_ERROR; 712e5b6d6dSopenharmony_ci * UChar* dest=NULL; 722e5b6d6dSopenharmony_ci * int32_t destCapacity=0; 732e5b6d6dSopenharmony_ci * int len =-1; 742e5b6d6dSopenharmony_ci * double elapsedTime = 0; 752e5b6d6dSopenharmony_ci * int retVal=0; 762e5b6d6dSopenharmony_ci * 772e5b6d6dSopenharmony_ci * UChar arr[5000]; 782e5b6d6dSopenharmony_ci * dest=arr; 792e5b6d6dSopenharmony_ci * destCapacity = 5000; 802e5b6d6dSopenharmony_ci * UTimer start; 812e5b6d6dSopenharmony_ci * 822e5b6d6dSopenharmony_ci * // Initialize cache and ensure the data is loaded. 832e5b6d6dSopenharmony_ci * // This loop checks for errors in Normalization. Once we pass the initialization 842e5b6d6dSopenharmony_ci * // without errors we can safelly assume that there are no errors while timing the 852e5b6d6dSopenharmony_ci * // function 862e5b6d6dSopenharmony_ci * for (loops=0; loops<10; loops++) { 872e5b6d6dSopenharmony_ci * for (line=0; line < gNumFileLines; line++) { 882e5b6d6dSopenharmony_ci * if (opt_uselen) { 892e5b6d6dSopenharmony_ci * len = fileLines[line].len; 902e5b6d6dSopenharmony_ci * } 912e5b6d6dSopenharmony_ci * 922e5b6d6dSopenharmony_ci * retVal= fn(fileLines[line].name,len,dest,destCapacity,&error); 932e5b6d6dSopenharmony_ci * #if U_PLATFORM_HAS_WIN32_API 942e5b6d6dSopenharmony_ci * if(retVal==0 ){ 952e5b6d6dSopenharmony_ci * fprintf(stderr,"Normalization of string in Windows API failed for mode %s. ErrorNo: %i at line number %i\n",mode,GetLastError(),line); 962e5b6d6dSopenharmony_ci * return 0; 972e5b6d6dSopenharmony_ci * } 982e5b6d6dSopenharmony_ci * #endif 992e5b6d6dSopenharmony_ci * if(U_FAILURE(error)){ 1002e5b6d6dSopenharmony_ci * fprintf(stderr,"Normalization of string in ICU API failed for mode %s. Error: %s at line number %i\n",mode,u_errorName(error),line); 1012e5b6d6dSopenharmony_ci * return 0; 1022e5b6d6dSopenharmony_ci * } 1032e5b6d6dSopenharmony_ci * 1042e5b6d6dSopenharmony_ci * } 1052e5b6d6dSopenharmony_ci * } 1062e5b6d6dSopenharmony_ci * 1072e5b6d6dSopenharmony_ci * //compute the time 1082e5b6d6dSopenharmony_ci * 1092e5b6d6dSopenharmony_ci * utimer_getTime(&start); 1102e5b6d6dSopenharmony_ci * for (loops=0; loops<loopCount; loops++) { 1112e5b6d6dSopenharmony_ci * for (line=0; line < gNumFileLines; line++) { 1122e5b6d6dSopenharmony_ci * if (opt_uselen) { 1132e5b6d6dSopenharmony_ci * len = fileLines[line].len; 1142e5b6d6dSopenharmony_ci * } 1152e5b6d6dSopenharmony_ci * 1162e5b6d6dSopenharmony_ci * retVal= fn(fileLines[line].name,len,dest,destCapacity,&error); 1172e5b6d6dSopenharmony_ci * 1182e5b6d6dSopenharmony_ci * } 1192e5b6d6dSopenharmony_ci * } 1202e5b6d6dSopenharmony_ci * 1212e5b6d6dSopenharmony_ci * return utimer_getElapsedSeconds(&start); 1222e5b6d6dSopenharmony_ci * } 1232e5b6d6dSopenharmony_ci * </code> 1242e5b6d6dSopenharmony_ci * 1252e5b6d6dSopenharmony_ci * iii) Let a higher level function do the calculation of confidence levels etc. 1262e5b6d6dSopenharmony_ci * Example: 1272e5b6d6dSopenharmony_ci * <code> 1282e5b6d6dSopenharmony_ci * void perf(UTimer* timer, UChar* source, int32_t sourceLen, UChar* target, int32_t targetLen, int32_t loopCount,UNormalizationMode mode, UErrorCode* error){ 1292e5b6d6dSopenharmony_ci * int32_t loops; 1302e5b6d6dSopenharmony_ci * for (loops=0; loops<loopCount; loops++) { 1312e5b6d6dSopenharmony_ci * unorm_normalize(source,sourceLen,target, targetLen,mode,error); 1322e5b6d6dSopenharmony_ci * } 1332e5b6d6dSopenharmony_ci * utimer_getTime(timer); 1342e5b6d6dSopenharmony_ci * } 1352e5b6d6dSopenharmony_ci * void main(const char* argsc, int argv){ 1362e5b6d6dSopenharmony_ci * // read the file and setup the data 1372e5b6d6dSopenharmony_ci * // set up options 1382e5b6d6dSopenharmony_ci * UTimer start,timer1, timer2, timer3, timer4; 1392e5b6d6dSopenharmony_ci * double NFDTimeTaken, NFCTimeTaken, FCDTimeTaken; 1402e5b6d6dSopenharmony_ci * switch(opt){ 1412e5b6d6dSopenharmony_ci * case 0: 1422e5b6d6dSopenharmony_ci * utimer_getTime(start); 1432e5b6d6dSopenharmony_ci * perf(timer1, source,sourceLen, target, targetLen,loopCount,UNORM_NFD,&error); 1442e5b6d6dSopenharmony_ci * NFDTimeTaken = utimer_getDeltaSeconds(start,timer1); 1452e5b6d6dSopenharmony_ci * case 1: 1462e5b6d6dSopenharmony_ci * timer_getTime(start); 1472e5b6d6dSopenharmony_ci * perf(timer2,source,sourceLen,target,targetLen,loopCount,UNORM_NFC,&error); 1482e5b6d6dSopenharmony_ci * NFCTimeTaken = utimer_getDeltaSeconds(start,timer2); 1492e5b6d6dSopenharmony_ci * perf(timer3, source, sourceLen, target,targetLen, loopCount, UNORM_FCD,&error); 1502e5b6d6dSopenharmony_ci * // ........so on ............. 1512e5b6d6dSopenharmony_ci * } 1522e5b6d6dSopenharmony_ci * // calculate confidence levels etc and print 1532e5b6d6dSopenharmony_ci * 1542e5b6d6dSopenharmony_ci * } 1552e5b6d6dSopenharmony_ci * 1562e5b6d6dSopenharmony_ci * </code> 1572e5b6d6dSopenharmony_ci * 1582e5b6d6dSopenharmony_ci */ 1592e5b6d6dSopenharmony_ci 1602e5b6d6dSopenharmony_citypedef struct UTimer UTimer; 1612e5b6d6dSopenharmony_ci 1622e5b6d6dSopenharmony_citypedef void FunctionToBeTimed(void* param); 1632e5b6d6dSopenharmony_ci 1642e5b6d6dSopenharmony_ci 1652e5b6d6dSopenharmony_ci#if U_PLATFORM_USES_ONLY_WIN32_API 1662e5b6d6dSopenharmony_ci 1672e5b6d6dSopenharmony_ci struct UTimer{ 1682e5b6d6dSopenharmony_ci LARGE_INTEGER start; 1692e5b6d6dSopenharmony_ci LARGE_INTEGER placeHolder; 1702e5b6d6dSopenharmony_ci }; 1712e5b6d6dSopenharmony_ci 1722e5b6d6dSopenharmony_cistatic int uprv_initFrequency(UTimer* timer) 1732e5b6d6dSopenharmony_ci { 1742e5b6d6dSopenharmony_ci return QueryPerformanceFrequency(&timer->placeHolder); 1752e5b6d6dSopenharmony_ci } 1762e5b6d6dSopenharmony_cistatic void uprv_start(UTimer* timer) 1772e5b6d6dSopenharmony_ci { 1782e5b6d6dSopenharmony_ci QueryPerformanceCounter(&timer->start); 1792e5b6d6dSopenharmony_ci } 1802e5b6d6dSopenharmony_cistatic double uprv_delta(UTimer* timer1, UTimer* timer2){ 1812e5b6d6dSopenharmony_ci return ((double)(timer2->start.QuadPart - timer1->start.QuadPart))/((double)timer1->placeHolder.QuadPart); 1822e5b6d6dSopenharmony_ci } 1832e5b6d6dSopenharmony_cistatic UBool uprv_compareFrequency(UTimer* timer1, UTimer* timer2){ 1842e5b6d6dSopenharmony_ci return (timer1->placeHolder.QuadPart == timer2->placeHolder.QuadPart); 1852e5b6d6dSopenharmony_ci } 1862e5b6d6dSopenharmony_ci 1872e5b6d6dSopenharmony_ci#else 1882e5b6d6dSopenharmony_ci 1892e5b6d6dSopenharmony_ci struct UTimer{ 1902e5b6d6dSopenharmony_ci struct timeval start; 1912e5b6d6dSopenharmony_ci struct timeval placeHolder; 1922e5b6d6dSopenharmony_ci }; 1932e5b6d6dSopenharmony_ci 1942e5b6d6dSopenharmony_cistatic int32_t uprv_initFrequency(UTimer* /*timer*/) 1952e5b6d6dSopenharmony_ci { 1962e5b6d6dSopenharmony_ci return 0; 1972e5b6d6dSopenharmony_ci } 1982e5b6d6dSopenharmony_cistatic void uprv_start(UTimer* timer) 1992e5b6d6dSopenharmony_ci { 2002e5b6d6dSopenharmony_ci gettimeofday(&timer->start, 0); 2012e5b6d6dSopenharmony_ci } 2022e5b6d6dSopenharmony_cistatic double uprv_delta(UTimer* timer1, UTimer* timer2){ 2032e5b6d6dSopenharmony_ci double t1, t2; 2042e5b6d6dSopenharmony_ci 2052e5b6d6dSopenharmony_ci t1 = (double)timer1->start.tv_sec + (double)timer1->start.tv_usec/(1000*1000); 2062e5b6d6dSopenharmony_ci t2 = (double)timer2->start.tv_sec + (double)timer2->start.tv_usec/(1000*1000); 2072e5b6d6dSopenharmony_ci return (t2-t1); 2082e5b6d6dSopenharmony_ci } 2092e5b6d6dSopenharmony_cistatic UBool uprv_compareFrequency(UTimer* /*timer1*/, UTimer* /*timer2*/){ 2102e5b6d6dSopenharmony_ci return true; 2112e5b6d6dSopenharmony_ci } 2122e5b6d6dSopenharmony_ci 2132e5b6d6dSopenharmony_ci#endif 2142e5b6d6dSopenharmony_ci/** 2152e5b6d6dSopenharmony_ci * Initializes the timer with the current time 2162e5b6d6dSopenharmony_ci * 2172e5b6d6dSopenharmony_ci * @param timer A pointer to UTimer struct to receive the current time 2182e5b6d6dSopenharmony_ci */ 2192e5b6d6dSopenharmony_cistatic inline void U_EXPORT2 2202e5b6d6dSopenharmony_ciutimer_getTime(UTimer* timer){ 2212e5b6d6dSopenharmony_ci uprv_initFrequency(timer); 2222e5b6d6dSopenharmony_ci uprv_start(timer); 2232e5b6d6dSopenharmony_ci} 2242e5b6d6dSopenharmony_ci 2252e5b6d6dSopenharmony_ci/** 2262e5b6d6dSopenharmony_ci * Returns the difference in times between timer1 and timer2 by subtracting 2272e5b6d6dSopenharmony_ci * timer1's time from timer2's time 2282e5b6d6dSopenharmony_ci * 2292e5b6d6dSopenharmony_ci * @param timer1 A pointer to UTimer struct to be used as starting time 2302e5b6d6dSopenharmony_ci * @param timer2 A pointer to UTimer struct to be used as end time 2312e5b6d6dSopenharmony_ci * @return Time in seconds 2322e5b6d6dSopenharmony_ci */ 2332e5b6d6dSopenharmony_cistatic inline double U_EXPORT2 2342e5b6d6dSopenharmony_ciutimer_getDeltaSeconds(UTimer* timer1, UTimer* timer2){ 2352e5b6d6dSopenharmony_ci if(uprv_compareFrequency(timer1,timer2)){ 2362e5b6d6dSopenharmony_ci return uprv_delta(timer1,timer2); 2372e5b6d6dSopenharmony_ci } 2382e5b6d6dSopenharmony_ci /* got error return -1 */ 2392e5b6d6dSopenharmony_ci return -1; 2402e5b6d6dSopenharmony_ci} 2412e5b6d6dSopenharmony_ci 2422e5b6d6dSopenharmony_ci/** 2432e5b6d6dSopenharmony_ci * Returns the time elapsed from the starting time represented by the 2442e5b6d6dSopenharmony_ci * UTimer struct pointer passed 2452e5b6d6dSopenharmony_ci * @param timer A pointer to UTimer struct to be used as starting time 2462e5b6d6dSopenharmony_ci * @return Time elapsed in seconds 2472e5b6d6dSopenharmony_ci */ 2482e5b6d6dSopenharmony_cistatic inline double U_EXPORT2 2492e5b6d6dSopenharmony_ciutimer_getElapsedSeconds(UTimer* timer){ 2502e5b6d6dSopenharmony_ci UTimer temp; 2512e5b6d6dSopenharmony_ci utimer_getTime(&temp); 2522e5b6d6dSopenharmony_ci return uprv_delta(timer,&temp); 2532e5b6d6dSopenharmony_ci} 2542e5b6d6dSopenharmony_ci 2552e5b6d6dSopenharmony_ci/** 2562e5b6d6dSopenharmony_ci * Executes the function pointed to for a given time and returns exact time 2572e5b6d6dSopenharmony_ci * taken and number of iterations of the loop 2582e5b6d6dSopenharmony_ci * @param thresholTimeVal 2592e5b6d6dSopenharmony_ci * @param loopCount output param to receive the number of iterations 2602e5b6d6dSopenharmony_ci * @param fn The function to be executed 2612e5b6d6dSopenharmony_ci * @param param Parameters to be passed to the fn 2622e5b6d6dSopenharmony_ci * @return the time elapsed in seconds 2632e5b6d6dSopenharmony_ci */ 2642e5b6d6dSopenharmony_cistatic inline double U_EXPORT2 2652e5b6d6dSopenharmony_ciutimer_loopUntilDone(double thresholdTimeVal, 2662e5b6d6dSopenharmony_ci int32_t* loopCount, 2672e5b6d6dSopenharmony_ci FunctionToBeTimed fn, 2682e5b6d6dSopenharmony_ci void* param){ 2692e5b6d6dSopenharmony_ci UTimer timer; 2702e5b6d6dSopenharmony_ci double currentVal=0; 2712e5b6d6dSopenharmony_ci *loopCount = 0; 2722e5b6d6dSopenharmony_ci utimer_getTime(&timer); 2732e5b6d6dSopenharmony_ci for(;currentVal<thresholdTimeVal;){ 2742e5b6d6dSopenharmony_ci fn(param); 2752e5b6d6dSopenharmony_ci currentVal = utimer_getElapsedSeconds(&timer); 2762e5b6d6dSopenharmony_ci (*loopCount)++; 2772e5b6d6dSopenharmony_ci } 2782e5b6d6dSopenharmony_ci return currentVal; 2792e5b6d6dSopenharmony_ci} 2802e5b6d6dSopenharmony_ci 2812e5b6d6dSopenharmony_ci#endif 2822e5b6d6dSopenharmony_ci 283