// Copyright (c) 1999-2012 OPEN CASCADE SAS // // The content of this file is subject to the Open CASCADE Technology Public // License Version 6.5 (the "License"). You may not use the content of this file // except in compliance with the License. Please obtain a copy of the License // at http://www.opencascade.org and read it completely before using this file. // // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. // // The Original Code and all software distributed under the License is // distributed on an "AS IS" basis, without warranty of any kind, and the // Initial Developer hereby disclaims all such warranties, including without // limitation, any warranties of merchantability, fitness for a particular // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. /*====================================================================== File : Perf.c Purpose : Set of functions to measure the CPU user time Author : Michael SAZONOV Created : 10/08/2000 History : 25/09/2001 : AGV : (const char *) in prototypes; search in table using hashvalue 09/11/2001 : AGV : Add functions perf_*_imeter for performance Add function perf_tick_meter ======================================================================*/ #include #include #include #include #include #ifndef WNT #include #endif /* Function times() is more precise than clock() because it does not take into account the system time and the time of child processes */ #include #ifdef WNT #define STRICT #include typedef __int64 PERF_TIME; #define PICK_TIME(_utime) { \ FILETIME t1, t2, ktime; \ GetThreadTimes (GetCurrentThread(), &t1, &t2, &ktime, (FILETIME *)&(_utime));\ } #define GET_SECONDS(_utime) (((double)(_utime))/10000000.) #else #include typedef clock_t PERF_TIME; #define PICK_TIME(_utime) { \ struct tms tmbuf; \ times (&tmbuf); \ (_utime) = tmbuf.tms_utime; \ } #ifndef CLK_TCK #define CLK_TCK 100 /* as SunOS */ #endif #define GET_SECONDS(_utime) (((double)(_utime))/CLK_TCK) #endif /*====================================================================== DEFINITIONS ======================================================================*/ typedef struct { char* name; /* identifier */ unsigned int hash; /* hash value */ PERF_TIME cumul_time; /* cumulative time */ PERF_TIME start_time; /* to store start time */ int nb_enter; /* number of enters */ } t_TimeCounter; #define MAX_METERS 100 static t_TimeCounter MeterTable[MAX_METERS]; static int nb_meters = 0; static t_TimeCounter* find_meter (const char * const MeterName); static t_TimeCounter* _perf_init_meter (const char * const MeterName, const int doFind); static unsigned int hash_value (const char * const aString); /*====================================================================== Function : perf_init_meter Purpose : Creates new counter (if it is absent) identified by MeterName and resets its cumulative value Returns : iMeter if OK, 0 if alloc problem ======================================================================*/ int perf_init_meter (const char * const MeterName) { t_TimeCounter* ptc = _perf_init_meter (MeterName, ~0); return (ptc ? (ptc-MeterTable)+1 : 0); } /*====================================================================== Function : perf_tick_meter Purpose : Increments the counter of meter MeterName without changing its state with respect to measurement of time. creates new meter if there is no such meter Returns : iMeter if OK, 0 if no such meter and cannot create a new one ======================================================================*/ int perf_tick_meter (const char * const MeterName) { t_TimeCounter* ptc = find_meter (MeterName); if (!ptc) { /* create new meter */ ptc = _perf_init_meter (MeterName, 0); } if (ptc) { ptc -> nb_enter ++; return (ptc-MeterTable) + 1; } return 0; } /*====================================================================== Function : perf_tick_imeter Purpose : Increments the counter of meter iMeter without changing its state with respect to measurement of time. Returns : iMeter if OK, 0 if no such meter ======================================================================*/ int perf_tick_imeter (const int iMeter) { if (iMeter > 0 && iMeter <= nb_meters) { MeterTable[iMeter-1].nb_enter ++; return iMeter; } return 0; } /*====================================================================== Function : perf_start_meter Purpose : Forces meter MeterName to begin to count by remembering the current data of timer; creates new meter if there is no such meter Returns : iMeter if OK, 0 if no such meter and cannot create a new one ======================================================================*/ int perf_start_meter (const char * const MeterName) { t_TimeCounter* ptc = find_meter (MeterName); if (!ptc) { /* create new meter */ ptc = _perf_init_meter (MeterName, 0); } if (ptc) { PICK_TIME (ptc->start_time) return (ptc - MeterTable) + 1; } return 0; } /*====================================================================== Function : perf_start_imeter Purpose : Forces meter with number iMeter to begin count by remembering the current data of timer; the meter must be previously created Returns : iMeter if OK, 0 if no such meter ======================================================================*/ int perf_start_imeter (const int iMeter) { if (iMeter > 0 && iMeter <= nb_meters) { t_TimeCounter * const ptc = &MeterTable[iMeter-1]; PICK_TIME (ptc->start_time) return iMeter; } return 0; } /*====================================================================== Function : perf_stop_meter Purpose : Forces meter MeterName to stop and cumulate time elapsed since start Returns : 1 if OK, 0 if no such meter or it is has not been started ======================================================================*/ int perf_stop_meter (const char * const MeterName) { t_TimeCounter* ptc = find_meter (MeterName); if (ptc && ptc->start_time) { PERF_TIME utime; PICK_TIME (utime) ptc->cumul_time += utime - ptc->start_time; ptc->start_time = 0; ptc->nb_enter++; return (ptc-MeterTable) + 1; } return 0; } /*====================================================================== Function : perf_stop_imeter Purpose : Forces meter with number iMeter to stop and cumulate the time elapsed since the start Returns : iMeter if OK, 0 if no such meter ======================================================================*/ int perf_stop_imeter (const int iMeter) { if (iMeter > 0 && iMeter <= nb_meters) { t_TimeCounter * const ptc = &MeterTable[iMeter-1]; if (ptc->start_time) { PERF_TIME utime; PICK_TIME (utime) ptc->cumul_time += utime - ptc->start_time; ptc->start_time = 0; ptc->nb_enter++; return iMeter; } } return 0; } /*====================================================================== Function : perf_get_meter Purpose : Tells the time cumulated by meter MeterName and the number of enters to this meter Output : *nb_enter, *seconds if the pointers != NULL Returns : iMeter if OK, 0 if no such meter ======================================================================*/ int perf_get_meter (const char * const MeterName, int * nb_enter, double * seconds) { t_TimeCounter* ptc = find_meter (MeterName); if (!ptc) return 0; if (nb_enter) *nb_enter = ptc->nb_enter; if (seconds) *seconds = GET_SECONDS(ptc->cumul_time); return (ptc-MeterTable) + 1; } /*====================================================================== Function : perf_print_all_meters Purpose : Prints on stdout the cumulated time and the number of enters for each meter in MeterTable; resets all meters Output : none Returns : none ======================================================================*/ void perf_print_all_meters (void) { int i; if (!nb_meters) return; printf (" Perf meter results : enters seconds enters/sec\n"); for (i=0; inb_enter) { double secs = GET_SECONDS(ptc->cumul_time); if (ptc->start_time) printf ("Warning : meter %s has not been stopped\n", ptc->name); printf ("%-40s : %7d %8.2f %10.2f\n", ptc->name, ptc->nb_enter, secs, (secs>0. ? ptc->nb_enter / secs : 0.)); ptc->cumul_time = 0; ptc->start_time = 0; ptc->nb_enter = 0; } } } /*====================================================================== Function : perf_close_meter Purpose : Prints out a meter and resets it Returns : none ======================================================================*/ void perf_close_meter (const char * const MeterName) { t_TimeCounter* ptc = find_meter (MeterName); if (ptc && ptc->nb_enter) { if (ptc->start_time) printf (" ===> Warning : meter %s has not been stopped\n", ptc->name); printf (" ===> [%s] : %d enters, %9.3f seconds\n", ptc->name, ptc->nb_enter, GET_SECONDS(ptc->cumul_time)); ptc->cumul_time = 0; ptc->start_time = 0; ptc->nb_enter = 0; } } /*====================================================================== Function : perf_destroy_all_meters Purpose : Deletes all meters and frees memory Returns : none ======================================================================*/ void perf_destroy_all_meters (void) { int i; for (i=0; i= MAX_METERS) return 0; ptc = &MeterTable[nb_meters]; ptc -> name = strdup (MeterName); if (!ptc -> name) return 0; ptc -> hash = hash_value (MeterName); nb_meters++; } ptc->cumul_time = 0; ptc->start_time = 0; ptc->nb_enter = 0; if (hasbeencalled == 0) { /*atexit (perf_print_and_destroy);*/ hasbeencalled = ~0; } return ptc; } /*====================================================================== Function : find_meter Purpose : Finds the meter MeterName in the MeterTable Returns : Pointer to meter object Remarks : For internal use in this module ======================================================================*/ static t_TimeCounter* find_meter (const char * const MeterName) { int i; const unsigned int aHash = hash_value (MeterName); for (i=0; i 0; i--) { const unsigned int bTmp = aCRC ^ (const unsigned int) (* aPtr++); aCRC = ((aCRC >> 8) ^ wCRC16a[bTmp & 0x0F]) ^ wCRC16b[(bTmp >> 4) & 0x0F]; } return aCRC; }