Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
7.5 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include <string.h>
#include <stdlib.h>
#include "basetypes.h"
#include "measure_section.h"
#include "convar.h"
// Static members
CMeasureSection *CMeasureSection::s_pSections = 0;
int CMeasureSection::s_nCount = 0;
double CMeasureSection::m_dNextResort = 0.0;
ConVar measure_resort( "measure_resort", "1.0", 0, "How often to re-sort profiling sections\n" );
ConVar game_speeds( "game_speeds","0" );
extern ConVar host_speeds;
//-----------------------------------------------------------------------------
// Purpose: Creates a profiling section
// Input : *name - name of the section ( allocated on stack hopefully )
//-----------------------------------------------------------------------------
CMeasureSection::CMeasureSection( const char *name )
{
// Just point at name since it's static
m_pszName = name;
// Clear accumulators
Reset();
SortReset();
m_dMaxTime.Init();
// Link into master list
m_pNext = s_pSections;
s_pSections = this;
// Update count
s_nCount++;
}
//-----------------------------------------------------------------------------
// Purpose: Destroys the object
//-----------------------------------------------------------------------------
CMeasureSection::~CMeasureSection( void )
{
m_pNext = NULL;
s_nCount--;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMeasureSection::UpdateMax( void )
{
if (m_dMaxTime.IsLessThan(m_dAccumulatedTime))
{
m_dMaxTime.Init();
CCycleCount::Add(m_dMaxTime,m_dAccumulatedTime,m_dMaxTime);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMeasureSection::Reset( void )
{
m_dAccumulatedTime.Init();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMeasureSection::SortReset( void )
{
m_dTotalTime.Init();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : const char
//-----------------------------------------------------------------------------
const char *CMeasureSection::GetName( void )
{
return m_pszName;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
CCycleCount const& CMeasureSection::GetTotalTime( void )
{
return m_dTotalTime;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
CCycleCount const& CMeasureSection::GetTime( void )
{
return m_dAccumulatedTime;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
CCycleCount const& CMeasureSection::GetMaxTime( void )
{
return m_dMaxTime;
}
//-----------------------------------------------------------------------------
// Purpose: Accumulates a timeslice
// Input : time -
//-----------------------------------------------------------------------------
void CMeasureSection::AddTime( CCycleCount const &rCount )
{
CCycleCount::Add(m_dAccumulatedTime, rCount, m_dAccumulatedTime);
CCycleCount::Add(m_dTotalTime, rCount, m_dTotalTime);
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : CMeasureSection
//-----------------------------------------------------------------------------
CMeasureSection *CMeasureSection::GetNext( void )
{
return m_pNext;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : CMeasureSection
//-----------------------------------------------------------------------------
CMeasureSection *CMeasureSection::GetList( void )
{
return s_pSections;
}
//-----------------------------------------------------------------------------
// Purpose: Compares accumulated time for two sections
// Input : ppms1 -
// ppms2 -
// Output : static int
//-----------------------------------------------------------------------------
static int SectionCompare( const void* ppms1,const void* ppms2 )
{
CMeasureSection* pms1 = *(CMeasureSection**)ppms1;
CMeasureSection* pms2 = *(CMeasureSection**)ppms2;
if ( pms1->GetTotalTime().IsLessThan(pms2->GetTotalTime()) )
return 1;
else
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: Sorts sections by time usage
//-----------------------------------------------------------------------------
void CMeasureSection::SortSections( void )
{
// Not enough to be sortable
if ( s_nCount <= 1 )
return;
CMeasureSection *sortarray[ 128 ];
CMeasureSection *ms;
memset(sortarray,sizeof(CMeasureSection*)*128,0);
ms = GetList();
int i;
int c = 0;
while ( ms )
{
sortarray[ c++ ] = ms;
ms = ms->GetNext();
}
// Sort the array alphabetically
qsort( sortarray, c , sizeof( CMeasureSection * ), SectionCompare );
// Fix next pointers
for ( i = 0; i < c-1; i++ )
{
sortarray[ i ]->m_pNext = sortarray[ i + 1 ];
}
sortarray[i]->m_pNext = NULL;
// Point head of list at it
s_pSections = sortarray[ 0 ];
}
//-----------------------------------------------------------------------------
// Purpose: Creates an instance for timing a section
// Input : *ms -
//-----------------------------------------------------------------------------
CMeasureSectionInstance::CMeasureSectionInstance( CMeasureSection *ms )
{
// Remember where to put accumulated time
m_pMS = ms;
if ( host_speeds.GetInt() < 3 && !game_speeds.GetInt())
return;
// Get initial timestamp
m_Timer.Start();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMeasureSectionInstance::~CMeasureSectionInstance( void )
{
if ( host_speeds.GetInt() < 3 && !game_speeds.GetInt())
return;
// Get final timestamp
m_Timer.End();
// Add time to section
m_pMS->AddTime( m_Timer.GetDuration() );
}
//-----------------------------------------------------------------------------
// Purpose: Re-sort all data and determine whether sort keys should be reset too ( after
// re-doing sort if needed ).
//-----------------------------------------------------------------------------
void ResetTimeMeasurements( void )
{
#if defined( _DEBUG ) || defined( FORCE_MEASURE )
bool sort_reset = false;
// Time to redo sort?
if ( measure_resort.GetFloat() > 0.0 &&
GetRealTime() >= CMeasureSection::m_dNextResort )
{
// Redo it
CMeasureSection::SortSections();
// Set next time
CMeasureSection::m_dNextResort = GetRealTime() + measure_resort.GetFloat();
// Flag to reset sort accumulator, too
sort_reset = true;
}
// Iterate through the sections now
CMeasureSection *p = CMeasureSection::GetList();
while ( p )
{
// Reset regular accum.
p->Reset();
// Reset sort accum less often
if ( sort_reset )
{
p->SortReset();
}
p = p->GetNext();
}
#endif
}