| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /***************************************************************************************************
- **
- ** Real-Time Hierarchical Profiling for Game Programming Gems 3
- **
- ** by Greg Hjelstrom & Byon Garrabrant
- **
- ***************************************************************************************************/
- // Credits: The Clock class was inspired by the Timer classes in
- // Ogre (www.ogre3d.org).
- #ifndef QUICK_PROF_H
- #define QUICK_PROF_H
- //To disable built-in profiling, please comment out next line
- //#define BT_NO_PROFILE 1
- #ifndef BT_NO_PROFILE
- #include "btScalar.h"
- #include "btAlignedAllocator.h"
- #include <new>
- //if you don't need btClock, you can comment next line
- #define USE_BT_CLOCK 1
- #ifdef USE_BT_CLOCK
- #ifdef __CELLOS_LV2__
- #include <sys/sys_time.h>
- #include <sys/time_util.h>
- #include <stdio.h>
- #endif
- #if defined (SUNOS) || defined (__SUNOS__)
- #include <stdio.h>
- #endif
- #if defined(WIN32) || defined(_WIN32)
- #define USE_WINDOWS_TIMERS
- #define WIN32_LEAN_AND_MEAN
- #define NOWINRES
- #define NOMCX
- #define NOIME
- #ifdef _XBOX
- #include <Xtl.h>
- #else
- #include <windows.h>
- #endif
- #include <time.h>
- #else
- #include <sys/time.h>
- #endif
- #define mymin(a,b) (a > b ? a : b)
- ///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
- class btClock
- {
- public:
- btClock()
- {
- #ifdef USE_WINDOWS_TIMERS
- QueryPerformanceFrequency(&mClockFrequency);
- #endif
- reset();
- }
- ~btClock()
- {
- }
- /// Resets the initial reference time.
- void reset()
- {
- #ifdef USE_WINDOWS_TIMERS
- QueryPerformanceCounter(&mStartTime);
- mStartTick = GetTickCount();
- mPrevElapsedTime = 0;
- #else
- #ifdef __CELLOS_LV2__
- typedef uint64_t ClockSize;
- ClockSize newTime;
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET( newTime );
- mStartTime = newTime;
- #else
- gettimeofday(&mStartTime, 0);
- #endif
- #endif
- }
- /// Returns the time in ms since the last call to reset or since
- /// the btClock was created.
- unsigned long int getTimeMilliseconds()
- {
- #ifdef USE_WINDOWS_TIMERS
- LARGE_INTEGER currentTime;
- QueryPerformanceCounter(¤tTime);
- LONGLONG elapsedTime = currentTime.QuadPart -
- mStartTime.QuadPart;
- // Compute the number of millisecond ticks elapsed.
- unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
- mClockFrequency.QuadPart);
- // Check for unexpected leaps in the Win32 performance counter.
- // (This is caused by unexpected data across the PCI to ISA
- // bridge, aka south bridge. See Microsoft KB274323.)
- unsigned long elapsedTicks = GetTickCount() - mStartTick;
- signed long msecOff = (signed long)(msecTicks - elapsedTicks);
- if (msecOff < -100 || msecOff > 100)
- {
- // Adjust the starting time forwards.
- LONGLONG msecAdjustment = mymin(msecOff *
- mClockFrequency.QuadPart / 1000, elapsedTime -
- mPrevElapsedTime);
- mStartTime.QuadPart += msecAdjustment;
- elapsedTime -= msecAdjustment;
- // Recompute the number of millisecond ticks elapsed.
- msecTicks = (unsigned long)(1000 * elapsedTime /
- mClockFrequency.QuadPart);
- }
- // Store the current elapsed time for adjustments next time.
- mPrevElapsedTime = elapsedTime;
- return msecTicks;
- #else
- #ifdef __CELLOS_LV2__
- uint64_t freq=sys_time_get_timebase_frequency();
- double dFreq=((double) freq) / 1000.0;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- SYS_TIMEBASE_GET( newTime );
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- return (unsigned long int)((double(newTime-mStartTime)) / dFreq);
- #else
- struct timeval currentTime;
- gettimeofday(¤tTime, 0);
- return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 +
- (currentTime.tv_usec - mStartTime.tv_usec) / 1000;
- #endif //__CELLOS_LV2__
- #endif
- }
- /// Returns the time in us since the last call to reset or since
- /// the Clock was created.
- unsigned long int getTimeMicroseconds()
- {
- #ifdef USE_WINDOWS_TIMERS
- LARGE_INTEGER currentTime;
- QueryPerformanceCounter(¤tTime);
- LONGLONG elapsedTime = currentTime.QuadPart -
- mStartTime.QuadPart;
- // Compute the number of millisecond ticks elapsed.
- unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
- mClockFrequency.QuadPart);
- // Check for unexpected leaps in the Win32 performance counter.
- // (This is caused by unexpected data across the PCI to ISA
- // bridge, aka south bridge. See Microsoft KB274323.)
- unsigned long elapsedTicks = GetTickCount() - mStartTick;
- signed long msecOff = (signed long)(msecTicks - elapsedTicks);
- if (msecOff < -100 || msecOff > 100)
- {
- // Adjust the starting time forwards.
- LONGLONG msecAdjustment = mymin(msecOff *
- mClockFrequency.QuadPart / 1000, elapsedTime -
- mPrevElapsedTime);
- mStartTime.QuadPart += msecAdjustment;
- elapsedTime -= msecAdjustment;
- }
- // Store the current elapsed time for adjustments next time.
- mPrevElapsedTime = elapsedTime;
- // Convert to microseconds.
- unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime /
- mClockFrequency.QuadPart);
- return usecTicks;
- #else
- #ifdef __CELLOS_LV2__
- uint64_t freq=sys_time_get_timebase_frequency();
- double dFreq=((double) freq)/ 1000000.0;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET( newTime );
- return (unsigned long int)((double(newTime-mStartTime)) / dFreq);
- #else
- struct timeval currentTime;
- gettimeofday(¤tTime, 0);
- return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 +
- (currentTime.tv_usec - mStartTime.tv_usec);
- #endif//__CELLOS_LV2__
- #endif
- }
- private:
- #ifdef USE_WINDOWS_TIMERS
- LARGE_INTEGER mClockFrequency;
- DWORD mStartTick;
- LONGLONG mPrevElapsedTime;
- LARGE_INTEGER mStartTime;
- #else
- #ifdef __CELLOS_LV2__
- uint64_t mStartTime;
- #else
- struct timeval mStartTime;
- #endif
- #endif //__CELLOS_LV2__
- };
- #endif //USE_BT_CLOCK
- ///A node in the Profile Hierarchy Tree
- class CProfileNode {
- public:
- CProfileNode( const char * name, CProfileNode * parent );
- ~CProfileNode( void );
- CProfileNode * Get_Sub_Node( const char * name );
- CProfileNode * Get_Parent( void ) { return Parent; }
- CProfileNode * Get_Sibling( void ) { return Sibling; }
- CProfileNode * Get_Child( void ) { return Child; }
- void CleanupMemory();
- void Reset( void );
- void Call( void );
- bool Return( void );
- const char * Get_Name( void ) { return Name; }
- int Get_Total_Calls( void ) { return TotalCalls; }
- float Get_Total_Time( void ) { return TotalTime; }
- protected:
- const char * Name;
- int TotalCalls;
- float TotalTime;
- unsigned long int StartTime;
- int RecursionCounter;
- CProfileNode * Parent;
- CProfileNode * Child;
- CProfileNode * Sibling;
- };
- ///An iterator to navigate through the tree
- class CProfileIterator
- {
- public:
- // Access all the children of the current parent
- void First(void);
- void Next(void);
- bool Is_Done(void);
- bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
- void Enter_Child( int index ); // Make the given child the new parent
- void Enter_Largest_Child( void ); // Make the largest child the new parent
- void Enter_Parent( void ); // Make the current parent's parent the new parent
- // Access the current child
- const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
- int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
- float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
- // Access the current parent
- const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
- int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
- float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
- protected:
- CProfileNode * CurrentParent;
- CProfileNode * CurrentChild;
- CProfileIterator( CProfileNode * start );
- friend class CProfileManager;
- };
- ///The Manager for the Profile system
- class CProfileManager {
- public:
- static void Start_Profile( const char * name );
- static void Stop_Profile( void );
- static void CleanupMemory(void)
- {
- Root.CleanupMemory();
- }
- static void Reset( void );
- static void Increment_Frame_Counter( void );
- static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
- static float Get_Time_Since_Reset( void );
- static CProfileIterator * Get_Iterator( void )
- {
-
- return new CProfileIterator( &Root );
- }
- static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
- static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
- static void dumpAll();
- private:
- static CProfileNode Root;
- static CProfileNode * CurrentNode;
- static int FrameCounter;
- static unsigned long int ResetTime;
- };
- ///ProfileSampleClass is a simple way to profile a function's scope
- ///Use the BT_PROFILE macro at the start of scope to time
- class CProfileSample {
- public:
- CProfileSample( const char * name )
- {
- CProfileManager::Start_Profile( name );
- }
- ~CProfileSample( void )
- {
- CProfileManager::Stop_Profile();
- }
- };
- #define BT_PROFILE( name ) CProfileSample __profile( name )
- #else
- #define BT_PROFILE( name )
- #endif //#ifndef BT_NO_PROFILE
- #endif //QUICK_PROF_H
|