Logo Search packages:      
Sourcecode: blender version File versions  Download package

btQuickprof.h

/***************************************************************************************************
**
** 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

#include "btScalar.h"
#include "LinearMath/btAlignedAllocator.h"
#include <new>
//To disable built-in profiling, please comment out next line
//#define BT_NO_PROFILE 1


//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.
00058 class btClock
{
public:
      btClock()
      {
#ifdef USE_WINDOWS_TIMERS
            QueryPerformanceFrequency(&mClockFrequency);
#endif
            reset();
      }

      ~btClock()
      {
      }

      /// Resets the initial reference time.
00074       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.
00097       unsigned long int getTimeMilliseconds()
      {
#ifdef USE_WINDOWS_TIMERS
            LARGE_INTEGER currentTime;
            QueryPerformanceCounter(&currentTime);
            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(&currentTime, 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.
00155       unsigned long int getTimeMicroseconds()
      {
#ifdef USE_WINDOWS_TIMERS
            LARGE_INTEGER currentTime;
            QueryPerformanceCounter(&currentTime);
            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(&currentTime, 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
00233 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
00268 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
00302 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); }

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
00334 class CProfileSample {
public:
      CProfileSample( const char * name )
      { 
            CProfileManager::Start_Profile( name ); 
      }

      ~CProfileSample( void )                         
      { 
            CProfileManager::Stop_Profile(); 
      }
};

#if !defined(BT_NO_PROFILE)
#define     BT_PROFILE( name )                  CProfileSample __profile( name )
#else
#define     BT_PROFILE( name )
#endif




#endif //QUICK_PROF_H



Generated by  Doxygen 1.6.0   Back to index