Back to index

supertuxkart  0.5+dfsg1
btQuickprof.h
Go to the documentation of this file.
00001 
00002 /***************************************************************************************************
00003 **
00004 ** Real-Time Hierarchical Profiling for Game Programming Gems 3
00005 **
00006 ** by Greg Hjelstrom & Byon Garrabrant
00007 **
00008 ***************************************************************************************************/
00009 
00010 // Credits: The Clock class was inspired by the Timer classes in 
00011 // Ogre (www.ogre3d.org).
00012 
00013 #ifndef QUICK_PROF_H
00014 #define QUICK_PROF_H
00015 
00016 #include "btScalar.h"
00017 
00018 //To disable built-in profiling, please comment out next line
00019 //#define BT_NO_PROFILE 1
00020 
00021 
00022 //if you don't need btClock, you can comment next line
00023 #define USE_BT_CLOCK 1
00024 
00025 #ifdef USE_BT_CLOCK
00026 #ifdef __CELLOS_LV2__
00027 #include <sys/sys_time.h>
00028 #include <sys/time_util.h>
00029 #include <stdio.h>
00030 typedef uint64_t __int64;
00031 #endif
00032 
00033 #if defined (SUNOS) || defined (__SUNOS__) 
00034 #include <stdio.h> 
00035 #endif
00036 
00037 #if defined(WIN32) || defined(_WIN32)
00038 
00039 #define USE_WINDOWS_TIMERS 
00040 #define WIN32_LEAN_AND_MEAN 
00041 #define NOWINRES 
00042 #define NOMCX 
00043 #define NOIME 
00044 #ifdef _XBOX
00045 #include <Xtl.h>
00046 #else
00047 #include <windows.h>
00048 #endif
00049 #include <time.h>
00050 
00051 #else
00052 #include <sys/time.h>
00053 #endif
00054 
00055 #define mymin(a,b) (a > b ? a : b)
00056 
00058 class btClock
00059 {
00060 public:
00061        btClock()
00062        {
00063 #ifdef USE_WINDOWS_TIMERS
00064               QueryPerformanceFrequency(&mClockFrequency);
00065 #endif
00066               reset();
00067        }
00068 
00069        ~btClock()
00070        {
00071        }
00072 
00074        void reset()
00075        {
00076 #ifdef USE_WINDOWS_TIMERS
00077               QueryPerformanceCounter(&mStartTime);
00078               mStartTick = GetTickCount();
00079               mPrevElapsedTime = 0;
00080 #else
00081 #ifdef __CELLOS_LV2__
00082 
00083               typedef uint64_t __int64;
00084               typedef __int64  ClockSize;
00085               ClockSize newTime;
00086               //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
00087               SYS_TIMEBASE_GET( newTime );
00088               mStartTime = newTime;
00089 #else
00090               gettimeofday(&mStartTime, 0);
00091 #endif
00092 
00093 #endif
00094        }
00095 
00098        unsigned long int getTimeMilliseconds()
00099        {
00100 #ifdef USE_WINDOWS_TIMERS
00101               LARGE_INTEGER currentTime;
00102               QueryPerformanceCounter(&currentTime);
00103               LONGLONG elapsedTime = currentTime.QuadPart - 
00104                      mStartTime.QuadPart;
00105 
00106               // Compute the number of millisecond ticks elapsed.
00107               unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
00108                      mClockFrequency.QuadPart);
00109 
00110               // Check for unexpected leaps in the Win32 performance counter.  
00111               // (This is caused by unexpected data across the PCI to ISA 
00112               // bridge, aka south bridge.  See Microsoft KB274323.)
00113               unsigned long elapsedTicks = GetTickCount() - mStartTick;
00114               signed long msecOff = (signed long)(msecTicks - elapsedTicks);
00115               if (msecOff < -100 || msecOff > 100)
00116               {
00117                      // Adjust the starting time forwards.
00118                      LONGLONG msecAdjustment = mymin(msecOff * 
00119                             mClockFrequency.QuadPart / 1000, elapsedTime - 
00120                             mPrevElapsedTime);
00121                      mStartTime.QuadPart += msecAdjustment;
00122                      elapsedTime -= msecAdjustment;
00123 
00124                      // Recompute the number of millisecond ticks elapsed.
00125                      msecTicks = (unsigned long)(1000 * elapsedTime / 
00126                             mClockFrequency.QuadPart);
00127               }
00128 
00129               // Store the current elapsed time for adjustments next time.
00130               mPrevElapsedTime = elapsedTime;
00131 
00132               return msecTicks;
00133 #else
00134 
00135 #ifdef __CELLOS_LV2__
00136               __int64 freq=sys_time_get_timebase_frequency();
00137               double dFreq=((double) freq) / 1000.0;
00138               typedef uint64_t __int64;
00139               typedef __int64  ClockSize;
00140               ClockSize newTime;
00141               SYS_TIMEBASE_GET( newTime );
00142               //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
00143 
00144               return (newTime-mStartTime) / dFreq;
00145 #else
00146 
00147               struct timeval currentTime;
00148               gettimeofday(&currentTime, 0);
00149               return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + 
00150                      (currentTime.tv_usec - mStartTime.tv_usec) / 1000;
00151 #endif //__CELLOS_LV2__
00152 #endif
00153        }
00154 
00157        unsigned long int getTimeMicroseconds()
00158        {
00159 #ifdef USE_WINDOWS_TIMERS
00160               LARGE_INTEGER currentTime;
00161               QueryPerformanceCounter(&currentTime);
00162               LONGLONG elapsedTime = currentTime.QuadPart - 
00163                      mStartTime.QuadPart;
00164 
00165               // Compute the number of millisecond ticks elapsed.
00166               unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
00167                      mClockFrequency.QuadPart);
00168 
00169               // Check for unexpected leaps in the Win32 performance counter.  
00170               // (This is caused by unexpected data across the PCI to ISA 
00171               // bridge, aka south bridge.  See Microsoft KB274323.)
00172               unsigned long elapsedTicks = GetTickCount() - mStartTick;
00173               signed long msecOff = (signed long)(msecTicks - elapsedTicks);
00174               if (msecOff < -100 || msecOff > 100)
00175               {
00176                      // Adjust the starting time forwards.
00177                      LONGLONG msecAdjustment = mymin(msecOff * 
00178                             mClockFrequency.QuadPart / 1000, elapsedTime - 
00179                             mPrevElapsedTime);
00180                      mStartTime.QuadPart += msecAdjustment;
00181                      elapsedTime -= msecAdjustment;
00182               }
00183 
00184               // Store the current elapsed time for adjustments next time.
00185               mPrevElapsedTime = elapsedTime;
00186 
00187               // Convert to microseconds.
00188               unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / 
00189                      mClockFrequency.QuadPart);
00190 
00191               return usecTicks;
00192 #else
00193 
00194 #ifdef __CELLOS_LV2__
00195               __int64 freq=sys_time_get_timebase_frequency();
00196               double dFreq=((double) freq)/ 1000000.0;
00197               typedef uint64_t __int64;
00198               typedef __int64  ClockSize;
00199               ClockSize newTime;
00200               //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
00201               SYS_TIMEBASE_GET( newTime );
00202 
00203               return (newTime-mStartTime) / dFreq;
00204 #else
00205 
00206               struct timeval currentTime;
00207               gettimeofday(&currentTime, 0);
00208               return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + 
00209                      (currentTime.tv_usec - mStartTime.tv_usec);
00210 #endif//__CELLOS_LV2__
00211 #endif 
00212        }
00213 
00214 private:
00215 #ifdef USE_WINDOWS_TIMERS
00216        LARGE_INTEGER mClockFrequency;
00217        DWORD mStartTick;
00218        LONGLONG mPrevElapsedTime;
00219        LARGE_INTEGER mStartTime;
00220 #else
00221 #ifdef __CELLOS_LV2__
00222        uint64_t      mStartTime;
00223 #else
00224        struct timeval mStartTime;
00225 #endif
00226 #endif //__CELLOS_LV2__
00227 
00228 };
00229 
00230 #endif //USE_BT_CLOCK
00231 
00232 
00233 
00234 
00235 /*
00236 ** A node in the Profile Hierarchy Tree
00237 */
00238 class  CProfileNode {
00239 
00240 public:
00241        CProfileNode( const char * name, CProfileNode * parent );
00242        ~CProfileNode( void );
00243 
00244        CProfileNode * Get_Sub_Node( const char * name );
00245 
00246        CProfileNode * Get_Parent( void )         { return Parent; }
00247        CProfileNode * Get_Sibling( void )        { return Sibling; }
00248        CProfileNode * Get_Child( void )                 { return Child; }
00249 
00250        void                        Reset( void );
00251        void                        Call( void );
00252        bool                        Return( void );
00253 
00254        const char *  Get_Name( void )                          { return Name; }
00255        int                         Get_Total_Calls( void )            { return TotalCalls; }
00256        float                       Get_Total_Time( void )             { return TotalTime; }
00257 
00258 protected:
00259 
00260        const char *  Name;
00261        int                         TotalCalls;
00262        float                       TotalTime;
00263        unsigned long int                  StartTime;
00264        int                         RecursionCounter;
00265 
00266        CProfileNode *       Parent;
00267        CProfileNode *       Child;
00268        CProfileNode *       Sibling;
00269 };
00270 
00271 /*
00272 ** An iterator to navigate through the tree
00273 */
00274 class CProfileIterator
00275 {
00276 public:
00277        // Access all the children of the current parent
00278        void                        First(void);
00279        void                        Next(void);
00280        bool                        Is_Done(void);
00281        bool                Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
00282 
00283        void                        Enter_Child( int index );          // Make the given child the new parent
00284        void                        Enter_Largest_Child( void );       // Make the largest child the new parent
00285        void                        Enter_Parent( void );                     // Make the current parent's parent the new parent
00286 
00287        // Access the current child
00288        const char *  Get_Current_Name( void )                  { return CurrentChild->Get_Name(); }
00289        int                         Get_Current_Total_Calls( void )    { return CurrentChild->Get_Total_Calls(); }
00290        float                       Get_Current_Total_Time( void )     { return CurrentChild->Get_Total_Time(); }
00291 
00292        // Access the current parent
00293        const char *  Get_Current_Parent_Name( void )                  { return CurrentParent->Get_Name(); }
00294        int                         Get_Current_Parent_Total_Calls( void )    { return CurrentParent->Get_Total_Calls(); }
00295        float                       Get_Current_Parent_Total_Time( void )     { return CurrentParent->Get_Total_Time(); }
00296 
00297 protected:
00298 
00299        CProfileNode *       CurrentParent;
00300        CProfileNode *       CurrentChild;
00301 
00302        CProfileIterator( CProfileNode * start );
00303        friend class         CProfileManager;
00304 };
00305 
00306 
00307 /*
00308 ** The Manager for the Profile system
00309 */
00310 class  CProfileManager {
00311 public:
00312        static void                                      Start_Profile( const char * name );
00313        static void                                      Stop_Profile( void );
00314 
00315        static void                                      Reset( void );
00316        static void                                      Increment_Frame_Counter( void );
00317        static int                                       Get_Frame_Count_Since_Reset( void )              { return FrameCounter; }
00318        static float                                     Get_Time_Since_Reset( void );
00319 
00320        static CProfileIterator *   Get_Iterator( void ) { return new CProfileIterator( &Root ); }
00321        static void                                      Release_Iterator( CProfileIterator * iterator ) { delete iterator; }
00322 
00323 private:
00324        static CProfileNode                Root;
00325        static CProfileNode *                     CurrentNode;
00326        static int                                       FrameCounter;
00327        static unsigned long int                                ResetTime;
00328 };
00329 
00330 
00331 /*
00332 ** ProfileSampleClass is a simple way to profile a function's scope
00333 ** Use the BT_PROFILE macro at the start of scope to time
00334 */
00335 class  CProfileSample {
00336 public:
00337        CProfileSample( const char * name )
00338        { 
00339               CProfileManager::Start_Profile( name ); 
00340        }
00341 
00342        ~CProfileSample( void )                                 
00343        { 
00344               CProfileManager::Stop_Profile(); 
00345        }
00346 };
00347 
00348 #if !defined(BT_NO_PROFILE)
00349 #define       BT_PROFILE( name )                 CProfileSample __profile( name )
00350 #else
00351 #define       BT_PROFILE( name )
00352 #endif
00353 
00354 
00355 
00356 
00357 #endif //QUICK_PROF_H
00358 
00359