Counter Strike : Global Offensive Source Code
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.

369 lines
10 KiB

  1. //========= Copyright c 1996-2008, Valve Corporation, All rights reserved. ============
  2. // This will contain things like helper functions to measure tick count of small pieces
  3. // of code precisely; or measure performance counters (L2 misses, mispredictions etc.)
  4. // on different hardware.
  5. //=====================================================================================
  6. // this class defines a section of code to measure
  7. #ifndef TIER0_MINIPROFILER_HDR
  8. #define TIER0_MINIPROFILER_HDR
  9. #include "microprofiler.h"
  10. #define ENABLE_MINI_PROFILER 0 // ENABLE_MICRO_PROFILER
  11. class CMiniProfiler;
  12. class CLinkedMiniProfiler;
  13. extern "C"
  14. {
  15. #if defined( STATIC_LINK )
  16. #define MINIPROFILER_DLL_LINKAGE extern
  17. #elif defined( TIER0_DLL_EXPORT )
  18. #define MINIPROFILER_DLL_LINKAGE DLL_EXPORT
  19. #else
  20. #define MINIPROFILER_DLL_LINKAGE DLL_IMPORT
  21. #endif
  22. MINIPROFILER_DLL_LINKAGE CMiniProfiler *g_pLastMiniProfiler;
  23. MINIPROFILER_DLL_LINKAGE CMiniProfiler *g_pRootMiniProfiler;
  24. MINIPROFILER_DLL_LINKAGE CLinkedMiniProfiler *g_pGlobalMiniProfilers;
  25. MINIPROFILER_DLL_LINKAGE CLinkedMiniProfiler *g_pAssertMiniProfilers;
  26. MINIPROFILER_DLL_LINKAGE uint32 g_nMiniProfilerFrame;
  27. MINIPROFILER_DLL_LINKAGE void PublishAll( CLinkedMiniProfiler * pList, uint32 nHistoryMax );
  28. MINIPROFILER_DLL_LINKAGE CMiniProfiler* PushMiniProfilerTS( CMiniProfiler *pProfiler );
  29. MINIPROFILER_DLL_LINKAGE void PopMiniProfilerTS( CMiniProfiler *pProfiler );
  30. MINIPROFILER_DLL_LINKAGE void AppendMiniProfilerToList( CLinkedMiniProfiler *pProfiler, CLinkedMiniProfiler **ppList );
  31. MINIPROFILER_DLL_LINKAGE void RemoveMiniProfilerFromList( CLinkedMiniProfiler *pProfiler );
  32. }
  33. #if ENABLE_MINI_PROFILER
  34. typedef CMicroProfilerSample CMiniProfilerSample;
  35. class CMiniProfiler: public CMicroProfiler
  36. {
  37. protected:
  38. uint64 m_numTimeBaseTicksInCallees; // this is the time to subtract from m_numTimeBaseTicks to get the "exclusive" time in this block
  39. public:
  40. CMiniProfiler()
  41. {
  42. Reset();
  43. }
  44. explicit CMiniProfiler( const CMicroProfiler &profiler ):
  45. CMicroProfiler( profiler ),
  46. m_numTimeBaseTicksInCallees( 0 )
  47. {
  48. }
  49. CMiniProfiler &operator=( const CMiniProfiler &other )
  50. {
  51. *(CMicroProfiler *)this = (const CMicroProfiler &)other;
  52. m_numTimeBaseTicksInCallees = other.m_numTimeBaseTicksInCallees;
  53. return *this;
  54. }
  55. void SubCallee( int64 numTimeBaseTicks )
  56. {
  57. m_numTimeBaseTicksInCallees += numTimeBaseTicks;
  58. }
  59. void Reset()
  60. {
  61. CMicroProfiler::Reset();
  62. m_numTimeBaseTicksInCallees = 0;
  63. }
  64. uint64 GetNumTimeBaseTicksInCallees() const
  65. {
  66. return m_numTimeBaseTicksInCallees;
  67. }
  68. int64 GetNumTimeBaseTicksExclusive( ) const
  69. {
  70. return m_numTimeBaseTicks - m_numTimeBaseTicksInCallees;
  71. }
  72. void Accumulate( const CMiniProfiler &other )
  73. {
  74. CMicroProfiler::Accumulate( other );
  75. m_numTimeBaseTicksInCallees += other.m_numTimeBaseTicksInCallees;
  76. }
  77. DLL_CLASS_EXPORT void Publish( const char *szMessage, ... );
  78. };
  79. #else
  80. class CMiniProfilerSample
  81. {
  82. public:
  83. int GetElapsed()const
  84. {
  85. return 0;
  86. }
  87. };
  88. class CMiniProfiler: public CMicroProfiler
  89. {
  90. public:
  91. CMiniProfiler() {}
  92. explicit CMiniProfiler( const CMicroProfiler &profiler ) :
  93. CMicroProfiler( profiler ){}
  94. CMiniProfiler &operator=( const CMiniProfiler &other ) { return *this; }
  95. void SubCallee( int64 numTimeBaseTicks ) {}
  96. uint64 GetNumTimeBaseTicksInCallees() const { return 0; }
  97. int64 GetNumTimeBaseTicksExclusive() const { return 0; }
  98. void Accumulate( const CMiniProfiler &other ) {}
  99. void Reset() {}
  100. void Damp( int shift = 1 ) {}
  101. void Publish( const char *szMessage, ... ) {}
  102. };
  103. #endif
  104. class CLinkedMiniProfiler: public CMiniProfiler
  105. {
  106. public:
  107. #if ENABLE_MINI_PROFILER
  108. CLinkedMiniProfiler *m_pNext, **m_ppPrev;
  109. const char *m_pName;
  110. const char *m_pLocation;
  111. CMiniProfiler *m_pLastParent; // for dynamic tracking of an approximate call tree
  112. CMiniProfiler *m_pDeclaredParent; // for static tracking of the logical dependency tree
  113. //uint32 m_nId;
  114. #endif
  115. public:
  116. CLinkedMiniProfiler( const char *pName, CLinkedMiniProfiler**ppList = &g_pGlobalMiniProfilers, CMiniProfiler *pDeclaredParent = NULL )
  117. {
  118. #if ENABLE_MINI_PROFILER
  119. m_pName = pName;
  120. m_pLocation = NULL;
  121. // NOTE: m_pNext and m_ppPrev have to be NULLs the first time around. This constructor can be called multiple times
  122. // from multiple threads, and there's no way to ensure the constructor isn't called twice. CNetworkGameServerBase::SV_PackEntity()
  123. // is an example of the function that enters from 2 threads and collides with itself in this constructor
  124. AppendMiniProfilerToList( this, ppList );
  125. m_pLastParent = NULL;
  126. m_pDeclaredParent = pDeclaredParent;
  127. #endif
  128. }
  129. CLinkedMiniProfiler( const char *pName, const char *pLocation )
  130. {
  131. #if ENABLE_MINI_PROFILER
  132. m_pName = pName;
  133. m_pLocation = pLocation;
  134. // NOTE: m_pNext and m_ppPrev have to be NULLs the first time around. This constructor can be called multiple times
  135. // from multiple threads, and there's no way to ensure the constructor isn't called twice. CNetworkGameServerBase::SV_PackEntity()
  136. // is an example of the function that enters from 2 threads and collides with itself in this constructor
  137. AppendMiniProfilerToList( this, &g_pGlobalMiniProfilers );
  138. m_pLastParent = NULL;
  139. m_pDeclaredParent = NULL;
  140. #endif
  141. }
  142. #if ENABLE_MINI_PROFILER
  143. CLinkedMiniProfiler *GetNext() { return m_pNext; }
  144. const char *GetName() const { return m_pName; }
  145. const char *GetLocation( )const { return m_pLocation; }
  146. #else
  147. CLinkedMiniProfiler *GetNext() { return NULL; }
  148. const char *GetName() const { return "DISABLED"; }
  149. const char *GetLocation( )const { return NULL; }
  150. #endif
  151. ~CLinkedMiniProfiler()
  152. {
  153. #if ENABLE_MINI_PROFILER
  154. RemoveMiniProfilerFromList( this );
  155. #endif
  156. }
  157. void Publish( uint nHistoryMax );
  158. void PurgeHistory();
  159. };
  160. class CAssertMiniProfiler: public CLinkedMiniProfiler
  161. {
  162. public:
  163. CAssertMiniProfiler( const char *pFunction, const char *pFile, int nLine ): CLinkedMiniProfiler( pFunction, &g_pAssertMiniProfilers )
  164. {
  165. m_pFile = pFile;
  166. m_nLine = nLine;
  167. m_bAsserted = false;
  168. }
  169. ~CAssertMiniProfiler()
  170. {
  171. }
  172. operator bool& () { return m_bAsserted; }
  173. void operator = ( bool bAsserted ){ m_bAsserted = bAsserted; }
  174. void operator = ( int bAsserted ) { m_bAsserted = (bAsserted != 0); }
  175. public:
  176. const char *m_pFile;
  177. int m_nLine;
  178. public:
  179. bool m_bAsserted;
  180. };
  181. template < class Sampler, bool bThreadSafe >
  182. class TMiniProfilerGuard: public Sampler
  183. {
  184. #if ENABLE_MINI_PROFILER
  185. CMiniProfiler *m_pProfiler, *m_pLastProfiler;
  186. int m_numCallsToAdd;
  187. #endif
  188. public:
  189. void Begin( CMiniProfiler *pProfiler, int numCallsToAdd )
  190. {
  191. #if ENABLE_MINI_PROFILER
  192. m_numCallsToAdd = numCallsToAdd;
  193. m_pProfiler = pProfiler;
  194. if ( bThreadSafe )
  195. {
  196. m_pLastProfiler = PushMiniProfilerTS( pProfiler );
  197. }
  198. else
  199. {
  200. m_pLastProfiler = g_pLastMiniProfiler;
  201. g_pLastMiniProfiler = pProfiler;
  202. }
  203. #endif
  204. }
  205. void SetCallCount( int numCalls )
  206. {
  207. #if ENABLE_MINI_PROFILER
  208. m_numCallsToAdd = numCalls;
  209. #endif
  210. }
  211. void AddCallCount( int addCalls )
  212. {
  213. #if ENABLE_MINI_PROFILER
  214. m_numCallsToAdd += addCalls;
  215. #endif
  216. }
  217. TMiniProfilerGuard( CLinkedMiniProfiler *pProfiler, int numCallsToAdd = 1 )
  218. {
  219. Begin( pProfiler, numCallsToAdd );
  220. #if ENABLE_MINI_PROFILER
  221. pProfiler->m_pLastParent = m_pLastProfiler;
  222. #endif
  223. }
  224. TMiniProfilerGuard( CMiniProfiler *pProfiler, int numCallsToAdd = 1 )
  225. {
  226. Begin( pProfiler, numCallsToAdd );
  227. }
  228. ~TMiniProfilerGuard( )
  229. {
  230. #if ENABLE_MINI_PROFILER
  231. int64 nElapsed = GetElapsed( );
  232. m_pProfiler->Add( nElapsed, m_numCallsToAdd );
  233. m_pLastProfiler->SubCallee( nElapsed );
  234. if ( bThreadSafe )
  235. {
  236. PopMiniProfilerTS( m_pLastProfiler );
  237. }
  238. else
  239. {
  240. g_pLastMiniProfiler = m_pLastProfiler;
  241. }
  242. #endif
  243. }
  244. };
  245. typedef TMiniProfilerGuard<CMiniProfilerSample, false> CMiniProfilerGuardFast; // default guard uses rdtsc
  246. typedef TMiniProfilerGuard<CMiniProfilerSample, true> CMiniProfilerGuard, CMiniProfilerGuardTS; // default guard uses rdtsc
  247. class CMiniProfilerGuardSimple: public CMiniProfilerSample
  248. {
  249. #if ENABLE_MINI_PROFILER
  250. CMiniProfiler *m_pProfiler, *m_pLastProfiler;
  251. #endif
  252. public:
  253. CMiniProfilerGuardSimple( CLinkedMiniProfiler *pProfiler )
  254. {
  255. #if ENABLE_MINI_PROFILER
  256. m_pProfiler = pProfiler;
  257. pProfiler->m_pLastParent = m_pLastProfiler = PushMiniProfilerTS( pProfiler ); // = g_pLastMiniProfiler; g_pLastMiniProfiler = pProfiler;
  258. #endif
  259. }
  260. ~CMiniProfilerGuardSimple()
  261. {
  262. #if ENABLE_MINI_PROFILER
  263. // Note: we measure both push and pop as if they belonged to the measured function
  264. PopMiniProfilerTS( m_pLastProfiler ); // g_pLastMiniProfiler = m_pLastProfiler;
  265. int64 nElapsed = GetElapsed( );
  266. m_pProfiler->Add( nElapsed );
  267. m_pLastProfiler->SubCallee( nElapsed );
  268. #endif
  269. }
  270. };
  271. class CMiniProfilerAntiGuard: public CMiniProfilerSample
  272. {
  273. #if ENABLE_MINI_PROFILER
  274. CMiniProfiler *m_pProfiler;
  275. #endif
  276. public:
  277. CMiniProfilerAntiGuard( CMiniProfiler *pProfiler )
  278. {
  279. #if ENABLE_MINI_PROFILER
  280. m_pProfiler = pProfiler;
  281. #endif
  282. }
  283. ~CMiniProfilerAntiGuard( )
  284. {
  285. #if ENABLE_MINI_PROFILER
  286. m_pProfiler->Add( -GetElapsed( ) );
  287. #endif
  288. }
  289. };
  290. #define MPROF_VAR_NAME_INTERNAL_CAT(a, b) a##b
  291. #define MPROF_VAR_NAME_INTERNAL( a, b ) MPROF_VAR_NAME_INTERNAL_CAT( a, b )
  292. #define MPROF_VAR_NAME( a ) MPROF_VAR_NAME_INTERNAL( a, __LINE__ )
  293. #define MPROF_TO_STRING_0( a ) #a
  294. #define MPROF_TO_STRING( a ) MPROF_TO_STRING_0(a)
  295. #ifdef PROJECTNAME
  296. #define MPROF_PROJECTNAME_STRING MPROF_TO_STRING(PROJECTNAME)
  297. #else
  298. #define MPROF_PROJECTNAME_STRING ""
  299. #endif
  300. #if ENABLE_MINI_PROFILER
  301. #define MPROF_GR( item, group ) static CLinkedMiniProfiler MPROF_VAR_NAME(miniProfilerNode)( ( item ), group "\n" __FUNCTION__ "\n" __FILE__ "\n" MPROF_TO_STRING( __LINE__ ) "\n" MPROF_PROJECTNAME_STRING ); CMiniProfilerGuardSimple MPROF_VAR_NAME( miniProfilerGuard )( &MPROF_VAR_NAME( miniProfilerNode ) )
  302. #else
  303. #define MPROF_GR( item, group )
  304. #endif
  305. #define MPROF_NODE( name, item, group ) CLinkedMiniProfiler miniprofiler_##name( ( item ), group "\n\n" __FILE__ "\n" MPROF_TO_STRING( __LINE__ ) "\n" MPROF_PROJECTNAME_STRING );
  306. #define MPROF_AUTO( name ) CMiniProfilerGuardSimple MPROF_VAR_NAME(miniProfiler_##name##_auto)( &miniprofiler_##name )
  307. #define MPROF_AUTO_FAST( name ) CMicroProfilerGuard MPROF_VAR_NAME(microProfiler_##name##_auto)( &miniprofiler_##name )
  308. #define MPROF_AUTO_FAST_COUNT( NAME, COUNT ) CMicroProfilerGuardWithCount MPROF_VAR_NAME(microProfiler_##NAME##_auto)( &miniprofiler_##NAME, COUNT )
  309. #define MPROF( item ) MPROF_GR( item, "" )
  310. #define MPROF_FN() MPROF( __FUNCTION__ )
  311. #endif