/*=========================================================================== * * Profile.H - Dave Humphrey (uesp@m0use.net), Thursday, November 23, 2000 * *=========================================================================*/ #ifndef __PROFILE_H #define __PROFILE_H /* Required Includes */ #include "genutil.h" #include "dbllist.h" #if defined(_WIN32) #include "windows.h" #endif /*=========================================================================== * * Begin Defines * *=========================================================================*/ /* Macros for inserting profiles, only valid in debug builds */ #if defined(_DEBUG) /* Start/end a named profile section */ #define START_PROFILE(Name) profile_t Name##Profile; \ SetStartProfile(Name##Profile); #define END_PROFILE(Name) SetEndProfile(Name##Profile); \ OutputProfile(Name##Profile, #Name); /* Increment/decrement the tab level output in the log file */ #define PROFILE_INC() IncreaseProfileTabs() #define PROFILE_DEC() DecreaseProfileTabs() /* Define macros for profiling functions */ #define START_FUNC_PROFILE() static CProfileRecord* pFuncProfile = ProfileList.AddTailData(CProfileRecord(__FUNC__)); \ profile_t FuncProfile; \ SetStartProfile(FuncProfile); #define END_FUNC_PROFILE() SetEndProfile(FuncProfile); \ pFuncProfile->AddProfileTime(FuncProfile); /* Profile a function from the call point */ #define PROFILE_FUNC2(Func,Name) static CProfileRecord* p##Name##Profile = ProfileList.AddTailData(CProfileRecord(#Name)); \ profile_t Name##Profile; \ SetStartProfile(Name##Profile); \ Func; \ SetEndProfile(Name##Profile); \ p##Name##Profile->AddProfileTime(Name##Profile); #define PROFILE_FUNC(Func) { static CProfileRecord* pFuncProfile = ProfileList.AddTailData(CProfileRecord(#Func)); \ profile_t FuncProfile; \ SetStartProfile(FuncProfile); \ Func; \ SetEndProfile(FuncProfile); \ pFuncProfile->AddProfileTime(FuncProfile); } /* Define profile macros to nothing in non-debug builds */ #else #define START_PROFILE(Name) #define END_PROFILE(Name) #define PROFILE_INC() #define PROFILE_DEC() #define START_FUNC_PROFILE() #define END_FUNC_PROFILE() #define PROFILE_FUNC2(Func,Name) Func; #define PROFILE_FUNC(Func) Func; #endif /*=========================================================================== * End of Defines *=========================================================================*/ /*=========================================================================== * * Begin Type and Structure Definitions * *=========================================================================*/ /* For recording the type of time counter used */ typedef enum { PROFILE_PERFORMANCE_COUNTER, PROFILE_CLOCK_COUNTER, PROFILE_NONE } profile_type_t; /* Type for recording profile times */ typedef struct profile_time_t { union { clock_t ClockCount; #if defined(_WIN32) LARGE_INTEGER TimerCount; #endif }; profile_type_t CountType; /* Overloaded operators */ profile_time_t& operator =(const long& Value); profile_time_t& operator =(const profile_time_t& Value); profile_time_t& operator +=(const profile_time_t& Value); profile_time_t& operator -=(const profile_time_t& Value); int operator ==(const long& Value); int operator ==(const profile_time_t& Value); int operator >(const profile_time_t& Value); int operator <(const profile_time_t& Value); operator float(void); friend profile_time_t operator +(const profile_time_t& Value1, const profile_time_t& Value2); friend profile_time_t operator -(const profile_time_t& Value1, const profile_time_t& Value2); friend profile_time_t operator +(const profile_time_t& Value1); friend profile_time_t operator -(const profile_time_t& Value1); } profile_time_t; /* Main profile type */ typedef struct { profile_time_t StartTime; profile_time_t EndTime; } profile_t; /*=========================================================================== * End of Type and Structure Definitions *=========================================================================*/ /*=========================================================================== * * Begin Class CProfileRecord Definition * * Defines a profile record which holds information about a profile point * in the source code. * *=========================================================================*/ class CProfileRecord { /*---------- Begin Protected Class Members --------------------*/ protected: char* pName; /* The name of the function or profile */ long ProfileCount; /* Number of times the function has been profiled */ profile_time_t ProfileTime; /* Total time the function has run */ profile_time_t MinTime; /* The max/min profile times */ profile_time_t MaxTime; /*---------- Begin Protected Class Methods --------------------*/ protected: /*---------- Begin Public Class Methods -----------------------*/ public: /* Class Constructors/Destructors */ CProfileRecord(); CProfileRecord(const char* pString); virtual ~CProfileRecord() { Destroy(); } virtual void Destroy (void); /* Adds a profile time to the net time/count for the record */ void AddProfileTime (const profile_t Profile); /* Get class members */ char* GetName (void) const { return (pName); } char* GetNiceName (void) const { return ((pName == NULL) ? "" : pName); } long GetProfileCount (void) const { return (ProfileCount); } profile_time_t GetProfileTime (void) const { return (ProfileTime); } profile_time_t GetMaxTime (void) const { return (MaxTime); } profile_time_t GetMinTime (void) const { return (MinTime); } /* Output profile information to a file stream */ boolean OutputProfile (FILE* pFileHandle = NULL); /* Set class members */ virtual void SetName (const char* pString) { DestroyPointerArray(pName); pName = CreateString(pString); } /* Overloaded operators */ CProfileRecord& operator =(const CProfileRecord& Record); }; /* A linked list of profile records */ typedef CDblListTemplate<CProfileRecord> CProfileList; /*=========================================================================== * End of Class CProfileRecord Definition *=========================================================================*/ /*=========================================================================== * * Begin Function Prototypes * *=========================================================================*/ /* Retrieve a time count */ void GetProfileTime (profile_time_t& ProfileTime); /* Output profile statistics to the profile log file */ void OutputProfile (profile_t& Profile, const char* pString); /* Outputs the current profile list to a file stream */ boolean OutputProfileList (FILE* pFileHandle = NULL); /*=========================================================================== * End of Function Prototypes *=========================================================================*/ /*=========================================================================== * * Begin External Variables * *=========================================================================*/ /* The default destination for all profiling output */ extern CLogFile ProfileLog; /* A list of all current function profiles */ extern CProfileList ProfileList; /*=========================================================================== * End of External Variables *=========================================================================*/ /*=========================================================================== * * Begin Inline Functions * *=========================================================================*/ /* Profile time copy operator for long values */ inline profile_time_t& profile_time_t::operator =(const long& Value) { #if defined(_WIN32) CountType = PROFILE_PERFORMANCE_COUNTER; TimerCount.QuadPart = (LONGLONG) Value; #else CountType = PROFILE_CLOCK_COUNTER; ClockCount = (clock_t) Value; #endif return (*this); } /* Profile time copy operator for a profile time value */ inline profile_time_t& profile_time_t::operator =(const profile_time_t& Value) { this->ClockCount = Value.ClockCount; this->CountType = Value.CountType; #if defined(_WIN32) this->TimerCount = Value.TimerCount; #endif return (*this); } /* Profile time compare operator for a long value */ inline int profile_time_t::operator ==(const long& Value) { switch (CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) return (int)(TimerCount.QuadPart == (LONGLONG) Value); #else return (int)(Value); #endif case PROFILE_CLOCK_COUNTER: return (int)(ClockCount == (clock_t) Value); default: return (1); } } /* Profile time greater than operator for two profile times */ inline int profile_time_t::operator >(const profile_time_t& Value) { if (CountType != Value.CountType) return (1); switch (CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) return (int)(TimerCount.QuadPart > Value.TimerCount.QuadPart); #else return (int)(1); #endif case PROFILE_CLOCK_COUNTER: return (int)(ClockCount > Value.ClockCount); default: return (1); } } /* Profile time less than operator for two profile times */ inline int profile_time_t::operator <(const profile_time_t& Value) { if (CountType != Value.CountType) return (1); switch (CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) return (int)(TimerCount.QuadPart < Value.TimerCount.QuadPart); #else return (int)(1); #endif case PROFILE_CLOCK_COUNTER: return (int)(ClockCount < Value.ClockCount); default: return (1); } } /* Profile time compare operator for two profile times */ inline int profile_time_t::operator ==(const profile_time_t& Value) { if (CountType != Value.CountType) return (1); switch (CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) return (int)(TimerCount.QuadPart == Value.TimerCount.QuadPart); #else return (int)(1); #endif case PROFILE_CLOCK_COUNTER: return (int)(ClockCount == Value.ClockCount); default: return (1); } } /* Profile time addition operator for two profile times */ inline profile_time_t operator +(const profile_time_t& Value1, const profile_time_t& Value2) { profile_time_t TempTime; /* Ignore if timer types are not equivalent */ if (Value1.CountType != Value2.CountType) return (Value1); TempTime.CountType = Value1.CountType; switch (Value1.CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) TempTime.TimerCount.QuadPart = Value1.TimerCount.QuadPart + Value2.TimerCount.QuadPart; return (TempTime); #else return (Value1); #endif case PROFILE_CLOCK_COUNTER: TempTime = Value1.ClockCount + Value2.ClockCount; return (TempTime); default: return (Value1); } } /* Profile time subtraction operator for two profile times */ inline profile_time_t operator -(const profile_time_t& Value1, const profile_time_t& Value2) { profile_time_t TempTime; /* Ignore if timer types are not equivalent */ if (Value1.CountType != Value2.CountType) return (Value1); TempTime.CountType = Value1.CountType; switch (Value1.CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) TempTime.TimerCount.QuadPart = Value1.TimerCount.QuadPart - Value2.TimerCount.QuadPart; return (TempTime); #else return (Value1); #endif case PROFILE_CLOCK_COUNTER: TempTime = Value1.ClockCount - Value2.ClockCount; return (TempTime); default: return (Value1); } } /* Profile time unary positive operator for two profile times */ inline profile_time_t operator +(const profile_time_t& Value) { return (Value); } /* Profile time unary negative operator for two profile times */ inline profile_time_t operator -(const profile_time_t& Value) { profile_time_t TempTime; TempTime.CountType = Value.CountType; switch (Value.CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) TempTime.TimerCount.QuadPart = -Value.TimerCount.QuadPart; return (TempTime); #else return (Value1); #endif case PROFILE_CLOCK_COUNTER: TempTime = -Value.ClockCount; return (TempTime); default: return (TempTime); } } /* Profile time addition assignment operator for a profile time */ inline profile_time_t& profile_time_t::operator +=(const profile_time_t& Value) { /* Ignore if timer types are not equivalent */ if (CountType != Value.CountType) return (*this); switch (CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) TimerCount.QuadPart += Value.TimerCount.QuadPart; #endif break; case PROFILE_CLOCK_COUNTER: ClockCount += Value.ClockCount; break; } return (*this); } /* Profile time substraction assignment operator for a profile time */ inline profile_time_t& profile_time_t::operator -=(const profile_time_t& Value) { /* Ignore if timer types are not equivalent */ if (CountType != Value.CountType) return (*this); switch (CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) TimerCount.QuadPart -= Value.TimerCount.QuadPart; #endif break; case PROFILE_CLOCK_COUNTER: ClockCount -= Value.ClockCount; break; } return (*this); } /* Convert a profile time to a float value */ inline profile_time_t::operator float(void) { switch (CountType) { case PROFILE_PERFORMANCE_COUNTER: #if defined(_WIN32) return (float) TimerCount.QuadPart; #elif return (float) 0.0; #endif case PROFILE_CLOCK_COUNTER: return (float) ClockCount; default: return (float) 0.0; } } /* Used to start and end a profile session */ inline void SetStartProfile (profile_t& Profile) { GetProfileTime(Profile.StartTime); } inline void SetEndProfile (profile_t& Profile) { GetProfileTime(Profile.EndTime); } /* Increase/descrease the number of padding tabs in the profile log */ inline void DecreaseProfileTabs (void) { ProfileLog.DecrementTabs(); } inline void IncreaseProfileTabs (void) { ProfileLog.IncrementTabs(); } /*=========================================================================== * End of Inline Functions *=========================================================================*/ #endif /*=========================================================================== * End of File Profile.H *=========================================================================*/