Home | History | Annotate | Download | only in unicode
      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