123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- /*
- Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- /*
- ***************************************************************************************************
- **
- ** profile.cpp
- **
- ** 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).
- #include "Bullet3Common/b3MinMax.h"
- #include "b3Quickprof.h"
- #ifndef B3_NO_PROFILE
- static b3Clock b3s_profileClock;
- inline void b3Profile_Get_Ticks(unsigned long int * ticks)
- {
- *ticks = b3s_profileClock.getTimeMicroseconds();
- }
- inline float b3Profile_Get_Tick_Rate(void)
- {
- // return 1000000.f;
- return 1000.f;
- }
- /***************************************************************************************************
- **
- ** b3ProfileNode
- **
- ***************************************************************************************************/
- /***********************************************************************************************
- * 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. *
- *=============================================================================================*/
- b3ProfileNode::b3ProfileNode( const char * name, b3ProfileNode * parent ) :
- Name( name ),
- TotalCalls( 0 ),
- TotalTime( 0 ),
- StartTime( 0 ),
- RecursionCounter( 0 ),
- Parent( parent ),
- Child( NULL ),
- Sibling( NULL ),
- m_userPtr(0)
- {
- Reset();
- }
- void b3ProfileNode::CleanupMemory()
- {
- delete ( Child);
- Child = NULL;
- delete ( Sibling);
- Sibling = NULL;
- }
- b3ProfileNode::~b3ProfileNode( 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. *
- *=============================================================================================*/
- b3ProfileNode * b3ProfileNode::Get_Sub_Node( const char * name )
- {
- // Try to find this sub node
- b3ProfileNode * child = Child;
- while ( child ) {
- if ( child->Name == name ) {
- return child;
- }
- child = child->Sibling;
- }
- // We didn't find it, so add it
-
- b3ProfileNode * node = new b3ProfileNode( name, this );
- node->Sibling = Child;
- Child = node;
- return node;
- }
- void b3ProfileNode::Reset( void )
- {
- TotalCalls = 0;
- TotalTime = 0.0f;
-
- if ( Child ) {
- Child->Reset();
- }
- if ( Sibling ) {
- Sibling->Reset();
- }
- }
- void b3ProfileNode::Call( void )
- {
- TotalCalls++;
- if (RecursionCounter++ == 0) {
- b3Profile_Get_Ticks(&StartTime);
- }
- }
- bool b3ProfileNode::Return( void )
- {
- if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
- unsigned long int time;
- b3Profile_Get_Ticks(&time);
- time-=StartTime;
- TotalTime += (float)time / b3Profile_Get_Tick_Rate();
- }
- return ( RecursionCounter == 0 );
- }
- /***************************************************************************************************
- **
- ** b3ProfileIterator
- **
- ***************************************************************************************************/
- b3ProfileIterator::b3ProfileIterator( b3ProfileNode * start )
- {
- CurrentParent = start;
- CurrentChild = CurrentParent->Get_Child();
- }
- void b3ProfileIterator::First(void)
- {
- CurrentChild = CurrentParent->Get_Child();
- }
- void b3ProfileIterator::Next(void)
- {
- CurrentChild = CurrentChild->Get_Sibling();
- }
- bool b3ProfileIterator::Is_Done(void)
- {
- return CurrentChild == NULL;
- }
- void b3ProfileIterator::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 b3ProfileIterator::Enter_Parent( void )
- {
- if ( CurrentParent->Get_Parent() != NULL ) {
- CurrentParent = CurrentParent->Get_Parent();
- }
- CurrentChild = CurrentParent->Get_Child();
- }
- /***************************************************************************************************
- **
- ** b3ProfileManager
- **
- ***************************************************************************************************/
- b3ProfileNode b3ProfileManager::Root( "Root", NULL );
- b3ProfileNode * b3ProfileManager::CurrentNode = &b3ProfileManager::Root;
- int b3ProfileManager::FrameCounter = 0;
- unsigned long int b3ProfileManager::ResetTime = 0;
- /***********************************************************************************************
- * b3ProfileManager::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 b3ProfileManager::Start_Profile( const char * name )
- {
- if (name != CurrentNode->Get_Name()) {
- CurrentNode = CurrentNode->Get_Sub_Node( name );
- }
-
- CurrentNode->Call();
- }
- /***********************************************************************************************
- * b3ProfileManager::Stop_Profile -- Stop timing and record the results. *
- *=============================================================================================*/
- void b3ProfileManager::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();
- }
- }
- /***********************************************************************************************
- * b3ProfileManager::Reset -- Reset the contents of the profiling system *
- * *
- * This resets everything except for the tree structure. All of the timing data is reset. *
- *=============================================================================================*/
- void b3ProfileManager::Reset( void )
- {
- b3s_profileClock.reset();
- Root.Reset();
- Root.Call();
- FrameCounter = 0;
- b3Profile_Get_Ticks(&ResetTime);
- }
- /***********************************************************************************************
- * b3ProfileManager::Increment_Frame_Counter -- Increment the frame counter *
- *=============================================================================================*/
- void b3ProfileManager::Increment_Frame_Counter( void )
- {
- FrameCounter++;
- }
- /***********************************************************************************************
- * b3ProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
- *=============================================================================================*/
- float b3ProfileManager::Get_Time_Since_Reset( void )
- {
- unsigned long int time;
- b3Profile_Get_Ticks(&time);
- time -= ResetTime;
- return (float)time / b3Profile_Get_Tick_Rate();
- }
- #include <stdio.h>
- void b3ProfileManager::dumpRecursive(b3ProfileIterator* profileIterator, int spacing)
- {
- profileIterator->First();
- if (profileIterator->Is_Done())
- return;
- float accumulated_time=0,parent_time = profileIterator->Is_Root() ? b3ProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
- int i;
- int frames_since_reset = b3ProfileManager::Get_Frame_Count_Since_Reset();
- for (i=0;i<spacing;i++) b3Printf(".");
- b3Printf("----------------------------------\n");
- for (i=0;i<spacing;i++) b3Printf(".");
- b3Printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time );
- float totalTime = 0.f;
-
- int numChildren = 0;
-
- for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
- {
- numChildren++;
- float current_total_time = profileIterator->Get_Current_Total_Time();
- accumulated_time += current_total_time;
- float fraction = parent_time > B3_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
- {
- int i; for (i=0;i<spacing;i++) b3Printf(".");
- }
- b3Printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
- totalTime += current_total_time;
- //recurse into children
- }
- if (parent_time < accumulated_time)
- {
- b3Printf("what's wrong\n");
- }
- for (i=0;i<spacing;i++) b3Printf(".");
- b3Printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > B3_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
-
- for (i=0;i<numChildren;i++)
- {
- profileIterator->Enter_Child(i);
- dumpRecursive(profileIterator,spacing+3);
- profileIterator->Enter_Parent();
- }
- }
- void b3ProfileManager::dumpAll()
- {
- b3ProfileIterator* profileIterator = 0;
- profileIterator = b3ProfileManager::Get_Iterator();
- dumpRecursive(profileIterator,0);
- b3ProfileManager::Release_Iterator(profileIterator);
- }
- void b3ProfileManager::dumpRecursive(FILE* f, b3ProfileIterator* profileIterator, int spacing)
- {
- profileIterator->First();
- if (profileIterator->Is_Done())
- return;
- float accumulated_time=0,parent_time = profileIterator->Is_Root() ? b3ProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
- int i;
- int frames_since_reset = b3ProfileManager::Get_Frame_Count_Since_Reset();
- for (i=0;i<spacing;i++) fprintf(f,".");
- fprintf(f,"----------------------------------\n");
- for (i=0;i<spacing;i++) fprintf(f,".");
- fprintf(f,"Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time );
- float totalTime = 0.f;
-
- int numChildren = 0;
-
- for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
- {
- numChildren++;
- float current_total_time = profileIterator->Get_Current_Total_Time();
- accumulated_time += current_total_time;
- float fraction = parent_time > B3_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
- {
- int i; for (i=0;i<spacing;i++) fprintf(f,".");
- }
- fprintf(f,"%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
- totalTime += current_total_time;
- //recurse into children
- }
- if (parent_time < accumulated_time)
- {
- fprintf(f,"what's wrong\n");
- }
- for (i=0;i<spacing;i++)
- fprintf(f,".");
- fprintf(f,"%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > B3_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
-
- for (i=0;i<numChildren;i++)
- {
- profileIterator->Enter_Child(i);
- dumpRecursive(f,profileIterator,spacing+3);
- profileIterator->Enter_Parent();
- }
- }
- void b3ProfileManager::dumpAll(FILE* f)
- {
- b3ProfileIterator* profileIterator = 0;
- profileIterator = b3ProfileManager::Get_Iterator();
- dumpRecursive(f, profileIterator,0);
- b3ProfileManager::Release_Iterator(profileIterator);
- }
- #endif //B3_NO_PROFILE
|