1 2 /*************************************************************************************************** 3 ** 4 ** Real-Time Hierarchical Profiling for Game Programming Gems 3 5 ** 6 ** by Greg Hjelstrom & Byon Garrabrant 7 ** 8 ***************************************************************************************************/ 9 10 // Credits: The Clock class was inspired by the Timer classes in 11 // Ogre (www.ogre3d.org). 12 13 14 15 #ifndef BT_QUICK_PROF_H 16 #define BT_QUICK_PROF_H 17 18 //To disable built-in profiling, please comment out next line 19 //#define BT_NO_PROFILE 1 20 #ifndef BT_NO_PROFILE 21 #include <stdio.h>//@todo remove this, backwards compatibility 22 #include "btScalar.h" 23 #include "btAlignedAllocator.h" 24 #include <new> 25 26 27 28 29 30 #define USE_BT_CLOCK 1 31 32 #ifdef USE_BT_CLOCK 33 34 ///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. 35 class btClock 36 { 37 public: 38 btClock(); 39 40 btClock(const btClock& other); 41 btClock& operator=(const btClock& other); 42 43 ~btClock(); 44 45 /// Resets the initial reference time. 46 void reset(); 47 48 /// Returns the time in ms since the last call to reset or since 49 /// the btClock was created. 50 unsigned long int getTimeMilliseconds(); 51 52 /// Returns the time in us since the last call to reset or since 53 /// the Clock was created. 54 unsigned long int getTimeMicroseconds(); 55 56 /// Returns the time in s since the last call to reset or since 57 /// the Clock was created. 58 btScalar getTimeSeconds(); 59 60 private: 61 struct btClockData* m_data; 62 }; 63 64 #endif //USE_BT_CLOCK 65 66 67 68 69 ///A node in the Profile Hierarchy Tree 70 class CProfileNode { 71 72 public: 73 CProfileNode( const char * name, CProfileNode * parent ); 74 ~CProfileNode( void ); 75 76 CProfileNode * Get_Sub_Node( const char * name ); 77 Get_Parent(void)78 CProfileNode * Get_Parent( void ) { return Parent; } Get_Sibling(void)79 CProfileNode * Get_Sibling( void ) { return Sibling; } Get_Child(void)80 CProfileNode * Get_Child( void ) { return Child; } 81 82 void CleanupMemory(); 83 void Reset( void ); 84 void Call( void ); 85 bool Return( void ); 86 Get_Name(void)87 const char * Get_Name( void ) { return Name; } Get_Total_Calls(void)88 int Get_Total_Calls( void ) { return TotalCalls; } Get_Total_Time(void)89 float Get_Total_Time( void ) { return TotalTime; } GetUserPointer()90 void* GetUserPointer() const {return m_userPtr;} SetUserPointer(void * ptr)91 void SetUserPointer(void* ptr) { m_userPtr = ptr;} 92 protected: 93 94 const char * Name; 95 int TotalCalls; 96 float TotalTime; 97 unsigned long int StartTime; 98 int RecursionCounter; 99 100 CProfileNode * Parent; 101 CProfileNode * Child; 102 CProfileNode * Sibling; 103 void* m_userPtr; 104 }; 105 106 ///An iterator to navigate through the tree 107 class CProfileIterator 108 { 109 public: 110 // Access all the children of the current parent 111 void First(void); 112 void Next(void); 113 bool Is_Done(void); Is_Root(void)114 bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } 115 116 void Enter_Child( int index ); // Make the given child the new parent 117 void Enter_Largest_Child( void ); // Make the largest child the new parent 118 void Enter_Parent( void ); // Make the current parent's parent the new parent 119 120 // Access the current child Get_Current_Name(void)121 const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } Get_Current_Total_Calls(void)122 int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } Get_Current_Total_Time(void)123 float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } 124 Get_Current_UserPointer(void)125 void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); } Set_Current_UserPointer(void * ptr)126 void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);} 127 // Access the current parent Get_Current_Parent_Name(void)128 const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } Get_Current_Parent_Total_Calls(void)129 int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } Get_Current_Parent_Total_Time(void)130 float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } 131 132 133 134 protected: 135 136 CProfileNode * CurrentParent; 137 CProfileNode * CurrentChild; 138 139 140 CProfileIterator( CProfileNode * start ); 141 friend class CProfileManager; 142 }; 143 144 145 ///The Manager for the Profile system 146 class CProfileManager { 147 public: 148 static void Start_Profile( const char * name ); 149 static void Stop_Profile( void ); 150 CleanupMemory(void)151 static void CleanupMemory(void) 152 { 153 Root.CleanupMemory(); 154 } 155 156 static void Reset( void ); 157 static void Increment_Frame_Counter( void ); Get_Frame_Count_Since_Reset(void)158 static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } 159 static float Get_Time_Since_Reset( void ); 160 Get_Iterator(void)161 static CProfileIterator * Get_Iterator( void ) 162 { 163 164 return new CProfileIterator( &Root ); 165 } Release_Iterator(CProfileIterator * iterator)166 static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } 167 168 static void dumpRecursive(CProfileIterator* profileIterator, int spacing); 169 170 static void dumpAll(); 171 172 private: 173 static CProfileNode Root; 174 static CProfileNode * CurrentNode; 175 static int FrameCounter; 176 static unsigned long int ResetTime; 177 }; 178 179 180 ///ProfileSampleClass is a simple way to profile a function's scope 181 ///Use the BT_PROFILE macro at the start of scope to time 182 class CProfileSample { 183 public: CProfileSample(const char * name)184 CProfileSample( const char * name ) 185 { 186 CProfileManager::Start_Profile( name ); 187 } 188 ~CProfileSample(void)189 ~CProfileSample( void ) 190 { 191 CProfileManager::Stop_Profile(); 192 } 193 }; 194 195 196 #define BT_PROFILE( name ) CProfileSample __profile( name ) 197 198 #else 199 200 #define BT_PROFILE( name ) 201 202 #endif //#ifndef BT_NO_PROFILE 203 204 205 206 #endif //BT_QUICK_PROF_H 207 208 209