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