📄 profile.cpp
字号:
/***************************************************************************************************
**
** profile.cpp
**
** Real-Time Hierarchical Profiling for Game Programming Gems 3
**
** by Greg Hjelstrom & Byon Garrabrant
**
***************************************************************************************************/
#include "stdafx.h"
#include <iostream.h>
#include <fstream.h>
#include "profile.h"inline void Profile_Get_Ticks(_int64 * ticks){ __asm { push edx; push ecx; mov ecx,ticks; _emit 0Fh _emit 31h mov [ecx],eax; mov [ecx+4],edx; pop ecx; pop edx; }}inline float Profile_Get_Tick_Rate(void){ static float _CPUFrequency = -1.0f; if (_CPUFrequency == -1.0f) { __int64 curr_rate = 0; ::QueryPerformanceFrequency ((LARGE_INTEGER *)&curr_rate); _CPUFrequency = (float)curr_rate; } return _CPUFrequency;}/***************************************************************************************************
**
** 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;
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();
}
}
// Changed from void to bool 6/02/03 TCF
bool CProfileIterator::Enter_Parent( void )
{
bool moved = false;
if ( CurrentParent->Get_Parent() != NULL ) {
CurrentParent = CurrentParent->Get_Parent();
moved = true;
}
CurrentChild = CurrentParent->Get_Child();
return moved;
}
/******************************************************************************************************* 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(); 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();}
/***********************************************************************************************
* CProfileManager::Write -- write the results to a file *
* Tyler C. Folsom 6/02/03 *
*=============================================================================================*/
void CProfileManager::Write( void )
{
float time = Get_Time_Since_Reset();
ofstream proFile( "Profile.txt", ios::out );
CProfileIterator *iter = Get_Iterator();
proFile << "Elapsed time: " << time << endl;
time = iter->Get_Current_Parent_Total_Time();
proFile << iter->Get_Current_Parent_Total_Calls() << '\t'
<< time << '\t'
<< iter->Get_Current_Parent_Name() << endl;
proFile.close();
Search( *iter );
Release_Iterator( iter );
proFile.close();
}
/***********************************************************************************************
* CProfileManager::Search -- recursive search of a node. *
* Tyler C. Folsom 6/02/03 *
*=============================================================================================*/
void CProfileManager::Search( CProfileIterator iter)
{
ofstream proFile( "Profile.txt", ios::app );
proFile << iter.Get_Current_Parent_Total_Calls() << '\t'
<< iter.Get_Current_Parent_Total_Time() << '\t'
<< iter.Get_Current_Parent_Name() << endl;
if (iter.Is_Done())
{ // no children
proFile.close();
return;
}
proFile << iter.Get_Current_Total_Calls() << '\t'
<< iter.Get_Current_Total_Time() << '\t'
<< iter.Get_Current_Name() << '\t'
<< iter.Get_Current_Parent_Name() << '\t';
if( iter.Get_Current_Parent_Total_Time() > 0)
proFile << iter.Get_Current_Total_Time() / iter.Get_Current_Parent_Total_Time();
proFile << endl;
proFile.close();
int i = 0;
for( ; !iter.Is_Done(); iter.Next() )
{ // siblings
iter.Enter_Child(i++);
Search( iter );
iter.Enter_Parent();
}
// iter.Enter_Parent();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -