mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-14 22:00:05 +00:00
ab8f16961e
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
404 lines
14 KiB
C++
404 lines
14 KiB
C++
/*
|
|
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
|