Game Develop C++ Platform: profile.h Source File

| Game Develop C++ Platform Platform for developing native games based on OpenGL and SFML with Game Develop

- Main Page
- Modules
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
profile.h
1 #if defined(GD_IDE_ONLY) || defined(DEBUG) || defined(DEV)
2
3 /***************************************************************************************************
4 **
5 ** Real-Time Hierarchical Profiling for Game Programming Gems 3
6 **
7 ** by Greg Hjelstrom & Byon Garrabrant
8 **
9 ***************************************************************************************************/
10
11 // Credits: The Clock class was inspired by the Timer classes in
12 // Ogre (www.ogre3d.org).
13 #ifndef QUICK_PROF_H
14 #define QUICK_PROF_H
15
16 //To disable built-in profiling, please comment out next line
17 //#define BT_NO_PROFILE 1
18 #ifndef BT_NO_PROFILE
19
20 #include "GDCpp/btScalar.h"
21 #include "GDCpp/btAlignedAllocator.h"
22 #include <new>
23
24 //if you don't need btClock, you can comment next line
25 #define USE_BT_CLOCK 1
26
27 #ifdef USE_BT_CLOCK
28 #ifdef __CELLOS_LV2__
29 #include <sys/sys_time.h>
30 #include <sys/time_util.h>
31 #include <stdio.h>
32 #endif
33
34 #if defined (SUNOS) || defined (__SUNOS__)
35 #include <stdio.h>
36 #endif
37
38 #if defined(WIN32) || defined(_WIN32)
39
40 #define USE_WINDOWS_TIMERS
41 #define WIN32_LEAN_AND_MEAN
42 #define NOWINRES
43 #define NOMCX
44 #define NOIME
45 #ifdef _XBOX
46 #include <Xtl.h>
47 #else
48
49 #include <windows.h>
50
51 #if defined(GD_IDE_ONLY)
52
53 #ifdef ___WXMSW___
54 #include <wx/msw/winundef.h>
55 #endif
56
57 #endif
58
59 #endif
60 #include <time.h>
61
62 #else
63 #include <sys/time.h>
64 #endif
65
66 #define mymin(a,b) (a > b ? a : b)
67
69 class btClock
70 {
71 public:
72 btClock()
73 {
74 #ifdef USE_WINDOWS_TIMERS
75 QueryPerformanceFrequency(&mClockFrequency);
76 #endif
77 reset();
78 }
79
80 ~btClock()
81 {
82 }
83
85 void reset()
86 {
87 #ifdef USE_WINDOWS_TIMERS
88 QueryPerformanceCounter(&mStartTime);
89 mStartTick = GetTickCount();
90 mPrevElapsedTime = 0;
91 #else
92 #ifdef __CELLOS_LV2__
93
94 typedef uint64_t ClockSize;
95 ClockSize newTime;
96 //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
97 SYS_TIMEBASE_GET( newTime );
98 mStartTime = newTime;
99 #else
100 gettimeofday(&mStartTime, 0);
101 #endif
102
103 #endif
104 }
105
108 unsigned long int getTimeMilliseconds()
109 {
110 #ifdef USE_WINDOWS_TIMERS
111 LARGE_INTEGER currentTime;
112 QueryPerformanceCounter(&currentTime);
113 LONGLONG elapsedTime = currentTime.QuadPart -
114 mStartTime.QuadPart;
115
116 // Compute the number of millisecond ticks elapsed.
117 unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
118 mClockFrequency.QuadPart);
119
120 // Check for unexpected leaps in the Win32 performance counter.
121 // (This is caused by unexpected data across the PCI to ISA
122 // bridge, aka south bridge. See Microsoft KB274323.)
123 unsigned long elapsedTicks = GetTickCount() - mStartTick;
124 signed long msecOff = (signed long)(msecTicks - elapsedTicks);
125 if (msecOff < -100 || msecOff > 100)
126 {
127 // Adjust the starting time forwards.
128 LONGLONG msecAdjustment = mymin(msecOff *
129 mClockFrequency.QuadPart / 1000, elapsedTime -
130 mPrevElapsedTime);
131 mStartTime.QuadPart += msecAdjustment;
132 elapsedTime -= msecAdjustment;
133
134 // Recompute the number of millisecond ticks elapsed.
135 msecTicks = (unsigned long)(1000 * elapsedTime /
136 mClockFrequency.QuadPart);
137 }
138
139 // Store the current elapsed time for adjustments next time.
140 mPrevElapsedTime = elapsedTime;
141
142 return msecTicks;
143 #else
144
145 #ifdef __CELLOS_LV2__
146 uint64_t freq=sys_time_get_timebase_frequency();
147 double dFreq=((double) freq) / 1000.0;
148 typedef uint64_t ClockSize;
149 ClockSize newTime;
150 SYS_TIMEBASE_GET( newTime );
151 //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
152
153 return (unsigned long int)((double(newTime-mStartTime)) / dFreq);
154 #else
155
156 struct timeval currentTime;
157 gettimeofday(&currentTime, 0);
158 return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 +
159 (currentTime.tv_usec - mStartTime.tv_usec) / 1000;
160 #endif //__CELLOS_LV2__
161 #endif
162 }
163
166 unsigned long int getTimeMicroseconds()
167 {
168 #ifdef USE_WINDOWS_TIMERS
169 LARGE_INTEGER currentTime;
170 QueryPerformanceCounter(&currentTime);
171 LONGLONG elapsedTime = currentTime.QuadPart -
172 mStartTime.QuadPart;
173
174 // Compute the number of millisecond ticks elapsed.
175 unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
176 mClockFrequency.QuadPart);
177
178 // Check for unexpected leaps in the Win32 performance counter.
179 // (This is caused by unexpected data across the PCI to ISA
180 // bridge, aka south bridge. See Microsoft KB274323.)
181 unsigned long elapsedTicks = GetTickCount() - mStartTick;
182 signed long msecOff = (signed long)(msecTicks - elapsedTicks);
183 if (msecOff < -100 || msecOff > 100)
184 {
185 // Adjust the starting time forwards.
186 LONGLONG msecAdjustment = mymin(msecOff *
187 mClockFrequency.QuadPart / 1000, elapsedTime -
188 mPrevElapsedTime);
189 mStartTime.QuadPart += msecAdjustment;
190 elapsedTime -= msecAdjustment;
191 }
192
193 // Store the current elapsed time for adjustments next time.
194 mPrevElapsedTime = elapsedTime;
195
196 // Convert to microseconds.
197 unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime /
198 mClockFrequency.QuadPart);
199
200 return usecTicks;
201 #else
202
203 #ifdef __CELLOS_LV2__
204 uint64_t freq=sys_time_get_timebase_frequency();
205 double dFreq=((double) freq)/ 1000000.0;
206 typedef uint64_t ClockSize;
207 ClockSize newTime;
208 //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
209 SYS_TIMEBASE_GET( newTime );
210
211 return (unsigned long int)((double(newTime-mStartTime)) / dFreq);
212 #else
213
214 struct timeval currentTime;
215 gettimeofday(&currentTime, 0);
216 return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 +
217 (currentTime.tv_usec - mStartTime.tv_usec);
218 #endif//__CELLOS_LV2__
219 #endif
220 }
221
222 private:
223 #ifdef USE_WINDOWS_TIMERS
224 LARGE_INTEGER mClockFrequency;
225 DWORD mStartTick;
226 LONGLONG mPrevElapsedTime;
227 LARGE_INTEGER mStartTime;
228 #else
229 #ifdef __CELLOS_LV2__
230 uint64_t mStartTime;
231 #else
232 struct timeval mStartTime;
233 #endif
234 #endif //__CELLOS_LV2__
235
236 };
237
238 #endif //USE_BT_CLOCK
239
241 class CProfileNode {
242
243 public:
244 CProfileNode( const char * name, CProfileNode * parent );
245 ~CProfileNode( void );
246
247 CProfileNode * Get_Sub_Node( const char * name );
248
249 CProfileNode * Get_Parent( void ) { return Parent; }
250 CProfileNode * Get_Sibling( void ) { return Sibling; }
251 CProfileNode * Get_Child( void ) { return Child; }
252
253 void CleanupMemory();
254 void Reset( void );
255 void Call( void );
256 bool Return( void );
257
258 const char * Get_Name( void ) { return Name; }
259 int Get_Total_Calls( void ) { return TotalCalls; }
260 float Get_Total_Time( void ) { return TotalTime; }
261
262 protected:
263
264 const char * Name;
265 int TotalCalls;
266 float TotalTime;
267 unsigned long int StartTime;
268 int RecursionCounter;
269
270 CProfileNode * Parent;
271 CProfileNode * Child;
272 CProfileNode * Sibling;
273 };
274
276 class CProfileIterator
277 {
278 public:
279 // Access all the children of the current parent
280 void First(void);
281 void Next(void);
282 bool Is_Done(void);
283 bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
284
285 void Enter_Child( int index ); // Make the given child the new parent
286 void Enter_Largest_Child( void ); // Make the largest child the new parent
287 void Enter_Parent( void ); // Make the current parent's parent the new parent
288
289 // Access the current child
290 const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
291 int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
292 float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
293
294 // Access the current parent
295 const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
296 int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
297 float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
298
299 protected:
300
301 CProfileNode * CurrentParent;
302 CProfileNode * CurrentChild;
303
304 CProfileIterator( CProfileNode * start );
305 friend class CProfileManager;
306 };
307
308
310 class GD_API CProfileManager {
311 public:
312 static void Start_Profile( const char * name );
313 static void Stop_Profile( void );
314
315 static void CleanupMemory(void)
316 {
317 Root.CleanupMemory();
318 }
319
320 static void Reset( void );
321 static void Increment_Frame_Counter( void );
322 static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
323 static float Get_Time_Since_Reset( void );
324
325 static CProfileIterator * Get_Iterator( void )
326 {
327
328 return new CProfileIterator( &Root );
329 }
330 static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
331
332 static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
333
334 static void dumpAll();
335
336 private:
337 static CProfileNode Root;
338 static CProfileNode * CurrentNode;
339 static int FrameCounter;
340 static unsigned long int ResetTime;
341 };
342
343
346 class CProfileSample {
347 public:
348 CProfileSample( const char * name )
349 {
350 CProfileManager::Start_Profile( name );
351 }
352
353 ~CProfileSample( void )
354 {
355 CProfileManager::Stop_Profile();
356 }
357 };
358
359
360 #define BT_PROFILE( name ) CProfileSample __profile( name )
361
362 #else
363
364 #define BT_PROFILE( name )
365
366 #endif //#ifndef BT_NO_PROFILE
367 #endif //QUICK_PROF_H
368
369 #undef LoadImage
370
371 #endif
372