Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifndef SMOOTH_AVERAGE_H
  7. #define SMOOTH_AVERAGE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "utldict.h"
  12. // Use this macro around any value, and it'll queue up the results given to it nTimes and
  13. // provide a running average.
  14. #define SMOOTH_AVERAGE( value, nCount ) CalcSmoothAverage( value, nCount, __FILE__, __LINE__ )
  15. // Same as their counterpart functions but they return more info in a CTimingInfo structure.
  16. #define SMOOTH_AVERAGE_STRUCT( value, nCount ) CalcSmoothAverage_Struct( value, nCount, __FILE__, __LINE__ )
  17. #define SUM_OVER_TIME_INTERVAL_STRUCT( value, nSeconds ) SumOverTimeInterval_Struct( value, nSeconds, __FILE__, __LINE__ )
  18. template< class T >
  19. class CTimingInfo
  20. {
  21. public:
  22. T m_AverageValue; // Note: this will be the SUM of the values if using SUM_OVER_TIME_INTERVAL.
  23. // The high and low points for m_AverageValue over the time interval.
  24. T m_HighAverage;
  25. T m_LowAverage;
  26. // The high and low points for the value itself over the time interval.
  27. T m_HighValue;
  28. T m_LowValue;
  29. };
  30. template< class T >
  31. class CAveragesInfo
  32. {
  33. public:
  34. class CEntry
  35. {
  36. public:
  37. T m_Average;
  38. T m_Value;
  39. };
  40. public:
  41. CUtlVector< CEntry > m_Values;
  42. int m_iCurValue;
  43. };
  44. template< class T >
  45. class CAveragesInfo_TimeBased
  46. {
  47. public:
  48. class CEntry
  49. {
  50. public:
  51. CCycleCount m_Time; // When this sample was taken.
  52. T m_Value;
  53. T m_Average;
  54. };
  55. CUtlVector<CEntry> m_Values;
  56. };
  57. #if 0
  58. template< class T >
  59. inline CTimingInfo< T > CalcSmoothAverage_Struct( const T &value, int nTimes, const char *pFilename, int iLine )
  60. {
  61. // Find an entry at this file and line.
  62. char fullStr[1024];
  63. Q_snprintf( fullStr, sizeof( fullStr ), "%s_%i", pFilename, iLine );
  64. int index = s_SmoothAverages.Find( fullStr );
  65. CAveragesInfo<T> *pInfo;
  66. if ( index == s_SmoothAverages.InvalidIndex() )
  67. {
  68. pInfo = new CAveragesInfo<T>;
  69. index = s_SmoothAverages.Insert( fullStr, pInfo );
  70. }
  71. else
  72. {
  73. pInfo = (CAveragesInfo<T>*)s_SmoothAverages[index];
  74. }
  75. // Add the new value.
  76. int newValueIndex;
  77. CAveragesInfo< T >::CEntry entry;
  78. entry.m_Value = value;
  79. if ( pInfo->m_Values.Count() < nTimes )
  80. {
  81. newValueIndex = pInfo->m_Values.AddToTail( entry );
  82. pInfo->m_iCurValue = 0;
  83. }
  84. else
  85. {
  86. newValueIndex = pInfo->m_iCurValue;
  87. pInfo->m_Values[pInfo->m_iCurValue] = entry;
  88. pInfo->m_iCurValue = (pInfo->m_iCurValue+1) % pInfo->m_Values.Count();
  89. }
  90. CTimingInfo< T > info;
  91. info.m_AverageValue = pInfo->m_Values[0].m_Value;
  92. info.m_HighAverage = pInfo->m_Values[0].m_Average;
  93. info.m_LowAverage = pInfo->m_Values[0].m_Average;
  94. info.m_HighValue = pInfo->m_Values[0].m_Value;
  95. info.m_LowValue = pInfo->m_Values[0].m_Value;
  96. for ( int i=1; i < pInfo->m_Values.Count(); i++ )
  97. {
  98. if ( i != newValueIndex )
  99. {
  100. info.m_HighAverage = max( pInfo->m_Values[i].m_Average, info.m_HighAverage );
  101. info.m_LowAverage = min( pInfo->m_Values[i].m_Average, info.m_LowAverage );
  102. }
  103. info.m_HighValue = max( pInfo->m_Values[i].m_Value, info.m_HighValue );
  104. info.m_LowValue = min( pInfo->m_Values[i].m_Value, info.m_LowValue );
  105. info.m_AverageValue += pInfo->m_Values[i].m_Value;
  106. }
  107. info.m_AverageValue /= pInfo->m_Values.Count();
  108. pInfo->m_Values[newValueIndex].m_Average = info.m_AverageValue;
  109. return info;
  110. }
  111. #endif
  112. template< class T >
  113. inline T CalcSmoothAverage( const T &value, int nTimes, const char *pFilename, int iLine )
  114. {
  115. CTimingInfo< T > info = CalcSmoothAverage_Struct( value, nTimes, pFilename, iLine );
  116. return info.m_AverageValue;
  117. };
  118. template< class T >
  119. inline CTimingInfo< T > SumOverTimeInterval_Struct( const T &value, float nSeconds, const char *pFilename, int iLine )
  120. {
  121. static CUtlDict< CAveragesInfo_TimeBased< T >*, int > s_SmoothAverages;
  122. char fullStr[1024];
  123. Q_snprintf( fullStr, sizeof( fullStr ), "%s_%i", pFilename, iLine );
  124. int index = s_SmoothAverages.Find( fullStr );
  125. CAveragesInfo_TimeBased<T> *pInfo;
  126. if ( index == s_SmoothAverages.InvalidIndex() )
  127. {
  128. pInfo = new CAveragesInfo_TimeBased<T>;
  129. index = s_SmoothAverages.Insert( fullStr, pInfo );
  130. }
  131. else
  132. {
  133. pInfo = s_SmoothAverages[index];
  134. }
  135. // Get the current time now.
  136. CCycleCount curTime;
  137. curTime.Sample();
  138. // Get rid of old samples.
  139. while ( pInfo->m_Values.Count() > 0 && (curTime.GetSeconds() - pInfo->m_Values[0].m_Time.GetSeconds()) > nSeconds )
  140. pInfo->m_Values.Remove( 0 );
  141. // Add on the new sample.
  142. typename CAveragesInfo_TimeBased< T >::CEntry newEntry;
  143. newEntry.m_Time = curTime;
  144. newEntry.m_Value = value;
  145. int newValueIndex = pInfo->m_Values.AddToTail( newEntry );
  146. CTimingInfo< T > info;
  147. info.m_AverageValue = pInfo->m_Values[0].m_Value;
  148. info.m_HighAverage = pInfo->m_Values[0].m_Average;
  149. info.m_LowAverage = pInfo->m_Values[0].m_Average;
  150. info.m_HighValue = pInfo->m_Values[0].m_Value;
  151. info.m_LowValue = pInfo->m_Values[0].m_Value;
  152. for ( int i=1; i < pInfo->m_Values.Count(); i++ )
  153. {
  154. if ( i != newValueIndex )
  155. {
  156. info.m_HighAverage = max( pInfo->m_Values[i].m_Average, info.m_HighAverage );
  157. info.m_LowAverage = min( pInfo->m_Values[i].m_Average, info.m_LowAverage );
  158. }
  159. info.m_HighValue = max( pInfo->m_Values[i].m_Value, info.m_HighValue );
  160. info.m_LowValue = min( pInfo->m_Values[i].m_Value, info.m_LowValue );
  161. info.m_AverageValue += pInfo->m_Values[i].m_Value;
  162. }
  163. info.m_AverageValue /= pInfo->m_Values.Count();
  164. pInfo->m_Values[newValueIndex].m_Average = info.m_AverageValue;
  165. return info;
  166. }
  167. template< class T >
  168. inline CTimingInfo< T > SumOverTimeInterval( const T &value, float nSeconds, const char *pFilename, int iLine )
  169. {
  170. CTimingInfo< T > info = SumOverTimeInterval_Struct( value, nSeconds, pFilename, iLine );
  171. return info.m_AverageValue;
  172. }
  173. #endif // SMOOTH_AVERAGE_H