Back to index

supertuxkart  0.5+dfsg1
btQuickprof.cpp
Go to the documentation of this file.
00001 /*
00002 
00003 /***************************************************************************************************
00004 **
00005 ** profile.cpp
00006 **
00007 ** Real-Time Hierarchical Profiling for Game Programming Gems 3
00008 **
00009 ** by Greg Hjelstrom & Byon Garrabrant
00010 **
00011 ***************************************************************************************************/
00012 
00013 // Credits: The Clock class was inspired by the Timer classes in 
00014 // Ogre (www.ogre3d.org).
00015 
00016 #include "LinearMath/btQuickprof.h"
00017 
00018 #ifdef USE_BT_CLOCK
00019 
00020 static btClock gProfileClock;
00021 
00022 inline void Profile_Get_Ticks(unsigned long int * ticks)
00023 {
00024        *ticks = gProfileClock.getTimeMicroseconds();
00025 }
00026 
00027 inline float Profile_Get_Tick_Rate(void)
00028 {
00029 //     return 1000000.f;
00030        return 1000.f;
00031 
00032 }
00033 
00034 
00035 
00036 /***************************************************************************************************
00037 **
00038 ** CProfileNode
00039 **
00040 ***************************************************************************************************/
00041 
00042 /***********************************************************************************************
00043  * INPUT:                                                                                      *
00044  * name - pointer to a static string which is the name of this profile node                    *
00045  * parent - parent pointer                                                                     *
00046  *                                                                                             *
00047  * WARNINGS:                                                                                   *
00048  * The name is assumed to be a static pointer, only the pointer is stored and compared for     *
00049  * efficiency reasons.                                                                         *
00050  *=============================================================================================*/
00051 CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
00052        Name( name ),
00053        TotalCalls( 0 ),
00054        TotalTime( 0 ),
00055        StartTime( 0 ),
00056        RecursionCounter( 0 ),
00057        Parent( parent ),
00058        Child( NULL ),
00059        Sibling( NULL )
00060 {
00061        Reset();
00062 }
00063 
00064 
00065 CProfileNode::~CProfileNode( void )
00066 {
00067        delete Child;
00068        delete Sibling;
00069 }
00070 
00071 
00072 /***********************************************************************************************
00073  * INPUT:                                                                                      *
00074  * name - static string pointer to the name of the node we are searching for                   *
00075  *                                                                                             *
00076  * WARNINGS:                                                                                   *
00077  * All profile names are assumed to be static strings so this function uses pointer compares   *
00078  * to find the named node.                                                                     *
00079  *=============================================================================================*/
00080 CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
00081 {
00082        // Try to find this sub node
00083        CProfileNode * child = Child;
00084        while ( child ) {
00085               if ( child->Name == name ) {
00086                      return child;
00087               }
00088               child = child->Sibling;
00089        }
00090 
00091        // We didn't find it, so add it
00092        CProfileNode * node = new CProfileNode( name, this );
00093        node->Sibling = Child;
00094        Child = node;
00095        return node;
00096 }
00097 
00098 
00099 void   CProfileNode::Reset( void )
00100 {
00101        TotalCalls = 0;
00102        TotalTime = 0.0f;
00103        gProfileClock.reset();
00104 
00105        if ( Child ) {
00106               Child->Reset();
00107        }
00108        if ( Sibling ) {
00109               Sibling->Reset();
00110        }
00111 }
00112 
00113 
00114 void   CProfileNode::Call( void )
00115 {
00116        TotalCalls++;
00117        if (RecursionCounter++ == 0) {
00118               Profile_Get_Ticks(&StartTime);
00119        }
00120 }
00121 
00122 
00123 bool   CProfileNode::Return( void )
00124 {
00125        if ( --RecursionCounter == 0 && TotalCalls != 0 ) { 
00126               unsigned long int time;
00127               Profile_Get_Ticks(&time);
00128               time-=StartTime;
00129               TotalTime += (float)time / Profile_Get_Tick_Rate();
00130        }
00131        return ( RecursionCounter == 0 );
00132 }
00133 
00134 
00135 /***************************************************************************************************
00136 **
00137 ** CProfileIterator
00138 **
00139 ***************************************************************************************************/
00140 CProfileIterator::CProfileIterator( CProfileNode * start )
00141 {
00142        CurrentParent = start;
00143        CurrentChild = CurrentParent->Get_Child();
00144 }
00145 
00146 
00147 void   CProfileIterator::First(void)
00148 {
00149        CurrentChild = CurrentParent->Get_Child();
00150 }
00151 
00152 
00153 void   CProfileIterator::Next(void)
00154 {
00155        CurrentChild = CurrentChild->Get_Sibling();
00156 }
00157 
00158 
00159 bool   CProfileIterator::Is_Done(void)
00160 {
00161        return CurrentChild == NULL;
00162 }
00163 
00164 
00165 void   CProfileIterator::Enter_Child( int index )
00166 {
00167        CurrentChild = CurrentParent->Get_Child();
00168        while ( (CurrentChild != NULL) && (index != 0) ) {
00169               index--;
00170               CurrentChild = CurrentChild->Get_Sibling();
00171        }
00172 
00173        if ( CurrentChild != NULL ) {
00174               CurrentParent = CurrentChild;
00175               CurrentChild = CurrentParent->Get_Child();
00176        }
00177 }
00178 
00179 
00180 void   CProfileIterator::Enter_Parent( void )
00181 {
00182        if ( CurrentParent->Get_Parent() != NULL ) {
00183               CurrentParent = CurrentParent->Get_Parent();
00184        }
00185        CurrentChild = CurrentParent->Get_Child();
00186 }
00187 
00188 
00189 /***************************************************************************************************
00190 **
00191 ** CProfileManager
00192 **
00193 ***************************************************************************************************/
00194 
00195 CProfileNode  CProfileManager::Root( "Root", NULL );
00196 CProfileNode *       CProfileManager::CurrentNode = &CProfileManager::Root;
00197 int                         CProfileManager::FrameCounter = 0;
00198 unsigned long int                  CProfileManager::ResetTime = 0;
00199 
00200 
00201 /***********************************************************************************************
00202  * CProfileManager::Start_Profile -- Begin a named profile                                    *
00203  *                                                                                             *
00204  * Steps one level deeper into the tree, if a child already exists with the specified name     *
00205  * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
00206  *                                                                                             *
00207  * INPUT:                                                                                      *
00208  * name - name of this profiling record                                                        *
00209  *                                                                                             *
00210  * WARNINGS:                                                                                   *
00211  * The string used is assumed to be a static string; pointer compares are used throughout      *
00212  * the profiling code for efficiency.                                                          *
00213  *=============================================================================================*/
00214 void   CProfileManager::Start_Profile( const char * name )
00215 {
00216        if (name != CurrentNode->Get_Name()) {
00217               CurrentNode = CurrentNode->Get_Sub_Node( name );
00218        } 
00219        
00220        CurrentNode->Call();
00221 }
00222 
00223 
00224 /***********************************************************************************************
00225  * CProfileManager::Stop_Profile -- Stop timing and record the results.                       *
00226  *=============================================================================================*/
00227 void   CProfileManager::Stop_Profile( void )
00228 {
00229        // Return will indicate whether we should back up to our parent (we may
00230        // be profiling a recursive function)
00231        if (CurrentNode->Return()) {
00232               CurrentNode = CurrentNode->Get_Parent();
00233        }
00234 }
00235 
00236 
00237 /***********************************************************************************************
00238  * CProfileManager::Reset -- Reset the contents of the profiling system                       *
00239  *                                                                                             *
00240  *    This resets everything except for the tree structure.  All of the timing data is reset.  *
00241  *=============================================================================================*/
00242 void   CProfileManager::Reset( void )
00243 { 
00244        Root.Reset();
00245     Root.Call();
00246        FrameCounter = 0;
00247        Profile_Get_Ticks(&ResetTime);
00248 }
00249 
00250 
00251 /***********************************************************************************************
00252  * CProfileManager::Increment_Frame_Counter -- Increment the frame counter                    *
00253  *=============================================================================================*/
00254 void CProfileManager::Increment_Frame_Counter( void )
00255 {
00256        FrameCounter++;
00257 }
00258 
00259 
00260 /***********************************************************************************************
00261  * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset         *
00262  *=============================================================================================*/
00263 float CProfileManager::Get_Time_Since_Reset( void )
00264 {
00265        unsigned long int time;
00266        Profile_Get_Ticks(&time);
00267        time -= ResetTime;
00268        return (float)time / Profile_Get_Tick_Rate();
00269 }
00270 
00271 #endif //USE_BT_CLOCK
00272