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.
222 lines
5.7 KiB
222 lines
5.7 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef SMOOTH_AVERAGE_H |
|
#define SMOOTH_AVERAGE_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
|
|
#include "utldict.h" |
|
|
|
|
|
|
|
// Use this macro around any value, and it'll queue up the results given to it nTimes and |
|
// provide a running average. |
|
#define SMOOTH_AVERAGE( value, nCount ) CalcSmoothAverage( value, nCount, __FILE__, __LINE__ ) |
|
|
|
|
|
// Same as their counterpart functions but they return more info in a CTimingInfo structure. |
|
#define SMOOTH_AVERAGE_STRUCT( value, nCount ) CalcSmoothAverage_Struct( value, nCount, __FILE__, __LINE__ ) |
|
#define SUM_OVER_TIME_INTERVAL_STRUCT( value, nSeconds ) SumOverTimeInterval_Struct( value, nSeconds, __FILE__, __LINE__ ) |
|
|
|
|
|
template< class T > |
|
class CTimingInfo |
|
{ |
|
public: |
|
T m_AverageValue; // Note: this will be the SUM of the values if using SUM_OVER_TIME_INTERVAL. |
|
|
|
// The high and low points for m_AverageValue over the time interval. |
|
T m_HighAverage; |
|
T m_LowAverage; |
|
|
|
// The high and low points for the value itself over the time interval. |
|
T m_HighValue; |
|
T m_LowValue; |
|
}; |
|
|
|
|
|
template< class T > |
|
class CAveragesInfo |
|
{ |
|
public: |
|
class CEntry |
|
{ |
|
public: |
|
T m_Average; |
|
T m_Value; |
|
}; |
|
|
|
public: |
|
CUtlVector< CEntry > m_Values; |
|
int m_iCurValue; |
|
}; |
|
|
|
|
|
template< class T > |
|
class CAveragesInfo_TimeBased |
|
{ |
|
public: |
|
class CEntry |
|
{ |
|
public: |
|
CCycleCount m_Time; // When this sample was taken. |
|
T m_Value; |
|
T m_Average; |
|
}; |
|
|
|
CUtlVector<CEntry> m_Values; |
|
}; |
|
|
|
|
|
#if 0 |
|
template< class T > |
|
inline CTimingInfo< T > CalcSmoothAverage_Struct( const T &value, int nTimes, const char *pFilename, int iLine ) |
|
{ |
|
// Find an entry at this file and line. |
|
char fullStr[1024]; |
|
Q_snprintf( fullStr, sizeof( fullStr ), "%s_%i", pFilename, iLine ); |
|
|
|
int index = s_SmoothAverages.Find( fullStr ); |
|
CAveragesInfo<T> *pInfo; |
|
if ( index == s_SmoothAverages.InvalidIndex() ) |
|
{ |
|
pInfo = new CAveragesInfo<T>; |
|
index = s_SmoothAverages.Insert( fullStr, pInfo ); |
|
} |
|
else |
|
{ |
|
pInfo = (CAveragesInfo<T>*)s_SmoothAverages[index]; |
|
} |
|
|
|
// Add the new value. |
|
int newValueIndex; |
|
CAveragesInfo< T >::CEntry entry; |
|
entry.m_Value = value; |
|
if ( pInfo->m_Values.Count() < nTimes ) |
|
{ |
|
newValueIndex = pInfo->m_Values.AddToTail( entry ); |
|
pInfo->m_iCurValue = 0; |
|
} |
|
else |
|
{ |
|
newValueIndex = pInfo->m_iCurValue; |
|
pInfo->m_Values[pInfo->m_iCurValue] = entry; |
|
pInfo->m_iCurValue = (pInfo->m_iCurValue+1) % pInfo->m_Values.Count(); |
|
} |
|
|
|
CTimingInfo< T > info; |
|
info.m_AverageValue = pInfo->m_Values[0].m_Value; |
|
|
|
info.m_HighAverage = pInfo->m_Values[0].m_Average; |
|
info.m_LowAverage = pInfo->m_Values[0].m_Average; |
|
|
|
info.m_HighValue = pInfo->m_Values[0].m_Value; |
|
info.m_LowValue = pInfo->m_Values[0].m_Value; |
|
|
|
for ( int i=1; i < pInfo->m_Values.Count(); i++ ) |
|
{ |
|
if ( i != newValueIndex ) |
|
{ |
|
info.m_HighAverage = max( pInfo->m_Values[i].m_Average, info.m_HighAverage ); |
|
info.m_LowAverage = min( pInfo->m_Values[i].m_Average, info.m_LowAverage ); |
|
} |
|
|
|
info.m_HighValue = max( pInfo->m_Values[i].m_Value, info.m_HighValue ); |
|
info.m_LowValue = min( pInfo->m_Values[i].m_Value, info.m_LowValue ); |
|
|
|
info.m_AverageValue += pInfo->m_Values[i].m_Value; |
|
} |
|
|
|
info.m_AverageValue /= pInfo->m_Values.Count(); |
|
pInfo->m_Values[newValueIndex].m_Average = info.m_AverageValue; |
|
return info; |
|
} |
|
#endif |
|
|
|
template< class T > |
|
inline T CalcSmoothAverage( const T &value, int nTimes, const char *pFilename, int iLine ) |
|
{ |
|
CTimingInfo< T > info = CalcSmoothAverage_Struct( value, nTimes, pFilename, iLine ); |
|
return info.m_AverageValue; |
|
}; |
|
|
|
|
|
template< class T > |
|
inline CTimingInfo< T > SumOverTimeInterval_Struct( const T &value, float nSeconds, const char *pFilename, int iLine ) |
|
{ |
|
static CUtlDict< CAveragesInfo_TimeBased< T >*, int > s_SmoothAverages; |
|
|
|
char fullStr[1024]; |
|
Q_snprintf( fullStr, sizeof( fullStr ), "%s_%i", pFilename, iLine ); |
|
|
|
int index = s_SmoothAverages.Find( fullStr ); |
|
CAveragesInfo_TimeBased<T> *pInfo; |
|
if ( index == s_SmoothAverages.InvalidIndex() ) |
|
{ |
|
pInfo = new CAveragesInfo_TimeBased<T>; |
|
index = s_SmoothAverages.Insert( fullStr, pInfo ); |
|
} |
|
else |
|
{ |
|
pInfo = s_SmoothAverages[index]; |
|
} |
|
|
|
// Get the current time now. |
|
CCycleCount curTime; |
|
curTime.Sample(); |
|
|
|
// Get rid of old samples. |
|
while ( pInfo->m_Values.Count() > 0 && (curTime.GetSeconds() - pInfo->m_Values[0].m_Time.GetSeconds()) > nSeconds ) |
|
pInfo->m_Values.Remove( 0 ); |
|
|
|
// Add on the new sample. |
|
typename CAveragesInfo_TimeBased< T >::CEntry newEntry; |
|
newEntry.m_Time = curTime; |
|
newEntry.m_Value = value; |
|
int newValueIndex = pInfo->m_Values.AddToTail( newEntry ); |
|
|
|
CTimingInfo< T > info; |
|
info.m_AverageValue = pInfo->m_Values[0].m_Value; |
|
|
|
info.m_HighAverage = pInfo->m_Values[0].m_Average; |
|
info.m_LowAverage = pInfo->m_Values[0].m_Average; |
|
|
|
info.m_HighValue = pInfo->m_Values[0].m_Value; |
|
info.m_LowValue = pInfo->m_Values[0].m_Value; |
|
|
|
for ( int i=1; i < pInfo->m_Values.Count(); i++ ) |
|
{ |
|
if ( i != newValueIndex ) |
|
{ |
|
info.m_HighAverage = max( pInfo->m_Values[i].m_Average, info.m_HighAverage ); |
|
info.m_LowAverage = min( pInfo->m_Values[i].m_Average, info.m_LowAverage ); |
|
} |
|
|
|
info.m_HighValue = max( pInfo->m_Values[i].m_Value, info.m_HighValue ); |
|
info.m_LowValue = min( pInfo->m_Values[i].m_Value, info.m_LowValue ); |
|
|
|
info.m_AverageValue += pInfo->m_Values[i].m_Value; |
|
} |
|
|
|
info.m_AverageValue /= pInfo->m_Values.Count(); |
|
pInfo->m_Values[newValueIndex].m_Average = info.m_AverageValue; |
|
return info; |
|
} |
|
|
|
|
|
template< class T > |
|
inline CTimingInfo< T > SumOverTimeInterval( const T &value, float nSeconds, const char *pFilename, int iLine ) |
|
{ |
|
CTimingInfo< T > info = SumOverTimeInterval_Struct( value, nSeconds, pFilename, iLine ); |
|
return info.m_AverageValue; |
|
} |
|
|
|
|
|
#endif // SMOOTH_AVERAGE_H |
|
|
|
|