213 lines
6.1 KiB
C++
213 lines
6.1 KiB
C++
//========= 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
|