added hierarchical profiling (needs more cleanup)

avoid dynamic allocations in btRaycastVehicle
This commit is contained in:
ejcoumans
2007-11-21 03:00:40 +00:00
parent 89382c0dc4
commit cab75b53ec
19 changed files with 695 additions and 128 deletions

View File

@@ -36,3 +36,266 @@ bool btProfiler::mFirstFileOutput = true;
btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod;
unsigned long int btProfiler::mCycleNumber = 0;
#endif //USE_QUICKPROF
/***************************************************************************************************
**
** profile.cpp
**
** Real-Time Hierarchical Profiling for Game Programming Gems 3
**
** by Greg Hjelstrom & Byon Garrabrant
**
***************************************************************************************************/
static btClock gProfileClock;
inline void Profile_Get_Ticks(_int64 * ticks)
{
*ticks = gProfileClock.getTimeMicroseconds();
}
inline float Profile_Get_Tick_Rate(void)
{
// return 1000000.f;
return 1000.f;
}
/***************************************************************************************************
**
** CProfileNode
**
***************************************************************************************************/
/***********************************************************************************************
* INPUT: *
* name - pointer to a static string which is the name of this profile node *
* parent - parent pointer *
* *
* WARNINGS: *
* The name is assumed to be a static pointer, only the pointer is stored and compared for *
* efficiency reasons. *
*=============================================================================================*/
CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
Name( name ),
TotalCalls( 0 ),
TotalTime( 0 ),
StartTime( 0 ),
RecursionCounter( 0 ),
Parent( parent ),
Child( NULL ),
Sibling( NULL )
{
Reset();
}
CProfileNode::~CProfileNode( void )
{
delete Child;
delete Sibling;
}
/***********************************************************************************************
* INPUT: *
* name - static string pointer to the name of the node we are searching for *
* *
* WARNINGS: *
* All profile names are assumed to be static strings so this function uses pointer compares *
* to find the named node. *
*=============================================================================================*/
CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
{
// Try to find this sub node
CProfileNode * child = Child;
while ( child ) {
if ( child->Name == name ) {
return child;
}
child = child->Sibling;
}
// We didn't find it, so add it
CProfileNode * node = new CProfileNode( name, this );
node->Sibling = Child;
Child = node;
return node;
}
void CProfileNode::Reset( void )
{
TotalCalls = 0;
TotalTime = 0.0f;
gProfileClock.reset();
if ( Child ) {
Child->Reset();
}
if ( Sibling ) {
Sibling->Reset();
}
}
void CProfileNode::Call( void )
{
TotalCalls++;
if (RecursionCounter++ == 0) {
Profile_Get_Ticks(&StartTime);
}
}
bool CProfileNode::Return( void )
{
if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
__int64 time;
Profile_Get_Ticks(&time);
time-=StartTime;
TotalTime += (float)time / Profile_Get_Tick_Rate();
}
return ( RecursionCounter == 0 );
}
/***************************************************************************************************
**
** CProfileIterator
**
***************************************************************************************************/
CProfileIterator::CProfileIterator( CProfileNode * start )
{
CurrentParent = start;
CurrentChild = CurrentParent->Get_Child();
}
void CProfileIterator::First(void)
{
CurrentChild = CurrentParent->Get_Child();
}
void CProfileIterator::Next(void)
{
CurrentChild = CurrentChild->Get_Sibling();
}
bool CProfileIterator::Is_Done(void)
{
return CurrentChild == NULL;
}
void CProfileIterator::Enter_Child( int index )
{
CurrentChild = CurrentParent->Get_Child();
while ( (CurrentChild != NULL) && (index != 0) ) {
index--;
CurrentChild = CurrentChild->Get_Sibling();
}
if ( CurrentChild != NULL ) {
CurrentParent = CurrentChild;
CurrentChild = CurrentParent->Get_Child();
}
}
void CProfileIterator::Enter_Parent( void )
{
if ( CurrentParent->Get_Parent() != NULL ) {
CurrentParent = CurrentParent->Get_Parent();
}
CurrentChild = CurrentParent->Get_Child();
}
/***************************************************************************************************
**
** CProfileManager
**
***************************************************************************************************/
CProfileNode CProfileManager::Root( "Root", NULL );
CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root;
int CProfileManager::FrameCounter = 0;
__int64 CProfileManager::ResetTime = 0;
/***********************************************************************************************
* CProfileManager::Start_Profile -- Begin a named profile *
* *
* Steps one level deeper into the tree, if a child already exists with the specified name *
* then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
* *
* INPUT: *
* name - name of this profiling record *
* *
* WARNINGS: *
* The string used is assumed to be a static string; pointer compares are used throughout *
* the profiling code for efficiency. *
*=============================================================================================*/
void CProfileManager::Start_Profile( const char * name )
{
if (name != CurrentNode->Get_Name()) {
CurrentNode = CurrentNode->Get_Sub_Node( name );
}
CurrentNode->Call();
}
/***********************************************************************************************
* CProfileManager::Stop_Profile -- Stop timing and record the results. *
*=============================================================================================*/
void CProfileManager::Stop_Profile( void )
{
// Return will indicate whether we should back up to our parent (we may
// be profiling a recursive function)
if (CurrentNode->Return()) {
CurrentNode = CurrentNode->Get_Parent();
}
}
/***********************************************************************************************
* CProfileManager::Reset -- Reset the contents of the profiling system *
* *
* This resets everything except for the tree structure. All of the timing data is reset. *
*=============================================================================================*/
void CProfileManager::Reset( void )
{
Root.Reset();
Root.Call();
FrameCounter = 0;
Profile_Get_Ticks(&ResetTime);
}
/***********************************************************************************************
* CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
*=============================================================================================*/
void CProfileManager::Increment_Frame_Counter( void )
{
FrameCounter++;
}
/***********************************************************************************************
* CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
*=============================================================================================*/
float CProfileManager::Get_Time_Since_Reset( void )
{
__int64 time;
Profile_Get_Ticks(&time);
time -= ResetTime;
return (float)time / Profile_Get_Tick_Rate();
}

View File

@@ -707,6 +707,139 @@ std::string btProfiler::createStatsString(BlockTimingMethod method)
#endif //USE_QUICKPROF
/***************************************************************************************************
**
** profile.h
**
** Real-Time Hierarchical Profiling for Game Programming Gems 3
**
** by Greg Hjelstrom & Byon Garrabrant
**
***************************************************************************************************/
/*
** A node in the Profile Hierarchy Tree
*/
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 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;
__int64 StartTime;
int RecursionCounter;
CProfileNode * Parent;
CProfileNode * Child;
CProfileNode * Sibling;
};
/*
** An iterator to navigate through the tree
*/
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
*/
class CProfileManager {
public:
static void Start_Profile( const char * name );
static void Stop_Profile( void );
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 __int64 ResetTime;
};
/*
** ProfileSampleClass is a simple way to profile a function's scope
** Use the PROFILE macro at the start of scope to time
*/
class CProfileSample {
public:
CProfileSample( const char * name )
{
CProfileManager::Start_Profile( name );
}
~CProfileSample( void )
{
CProfileManager::Stop_Profile();
}
};
#if !defined(NO_PROFILE)
#define PROFILE( name ) CProfileSample __profile( name )
#else
#define PROFILE( name )
#endif
#endif //QUICK_PROF_H