wwprofile.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWDebug *
  23. * *
  24. * $Archive:: /Commando/Code/wwdebug/wwprofile.h $*
  25. * *
  26. * $Author:: Jani_p $*
  27. * *
  28. * $Modtime:: 3/25/02 2:05p $*
  29. * *
  30. * $Revision:: 14 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #if _MSC_VER >= 1000
  36. #pragma once
  37. #endif // _MSC_VER >= 1000
  38. //#define ENABLE_TIME_AND_MEMORY_LOG
  39. #ifndef WWPROFILE_H
  40. #define WWPROFILE_H
  41. #include "wwstring.h"
  42. #ifdef _UNIX
  43. typedef signed long long __int64;
  44. typedef signed long long _int64;
  45. #endif
  46. // enable profiling by default in debug mode.
  47. #ifdef WWDEBUG
  48. #define ENABLE_WWPROFILE
  49. #endif
  50. extern unsigned WWProfile_Get_System_Time(); // timeGetTime() wrapper
  51. class FileClass;
  52. /*
  53. ** A node in the WWProfile Hierarchy Tree
  54. */
  55. class WWProfileHierachyNodeClass {
  56. public:
  57. WWProfileHierachyNodeClass( const char * name, WWProfileHierachyNodeClass * parent );
  58. WWProfileHierachyNodeClass( unsigned id, WWProfileHierachyNodeClass * parent );
  59. ~WWProfileHierachyNodeClass( void );
  60. WWProfileHierachyNodeClass * Get_Sub_Node( const char * name );
  61. WWProfileHierachyNodeClass * Get_Parent( void ) { return Parent; }
  62. WWProfileHierachyNodeClass * Get_Sibling( void ) { return Sibling; }
  63. WWProfileHierachyNodeClass * Get_Child( void ) { return Child; }
  64. void Set_Parent( WWProfileHierachyNodeClass *node ) { Parent=node; }
  65. void Set_Sibling( WWProfileHierachyNodeClass *node ) { Sibling=node; }
  66. void Set_Child( WWProfileHierachyNodeClass *node ) { Child=node; }
  67. void Reset( void );
  68. void Call( void );
  69. bool Return( void );
  70. const char * Get_Name( void ) { return Name; }
  71. int Get_Total_Calls( void ) { return TotalCalls; }
  72. float Get_Total_Time( void ) { return TotalTime; }
  73. void Set_Total_Calls(int calls) { TotalCalls=calls; }
  74. void Set_Total_Time(float time) { TotalTime=time; }
  75. WWProfileHierachyNodeClass* Clone_Hierarchy(WWProfileHierachyNodeClass* parent);
  76. void Write_To_File(FileClass* file,int recursion);
  77. void Add_To_String_Compact(StringClass& string,int recursion);
  78. protected:
  79. const char * Name;
  80. int TotalCalls;
  81. float TotalTime;
  82. __int64 StartTime;
  83. int RecursionCounter;
  84. unsigned ProfileStringID;
  85. WWProfileHierachyNodeClass * Parent;
  86. WWProfileHierachyNodeClass * Child;
  87. WWProfileHierachyNodeClass * Sibling;
  88. };
  89. class WWProfileHierachyInfoClass {
  90. public:
  91. WWProfileHierachyInfoClass( const char * name, WWProfileHierachyInfoClass * parent );
  92. ~WWProfileHierachyInfoClass( void );
  93. WWProfileHierachyInfoClass * Get_Parent( void ) { return Parent; }
  94. WWProfileHierachyInfoClass * Get_Sibling( void ) { return Sibling; }
  95. WWProfileHierachyInfoClass * Get_Child( void ) { return Child; }
  96. void Set_Parent( WWProfileHierachyInfoClass *node ) { Parent=node; }
  97. void Set_Sibling( WWProfileHierachyInfoClass *node ) { Sibling=node; }
  98. void Set_Child( WWProfileHierachyInfoClass *node ) { Child=node; }
  99. const char * Get_Name( void ) { return Name; }
  100. void Set_Name( const char* name ) { Name=name; }
  101. int Get_Total_Calls( void ) { return TotalCalls; }
  102. float Get_Total_Time( void ) { return TotalTime; }
  103. void Set_Total_Calls(int calls) { TotalCalls=calls; }
  104. void Set_Total_Time(float time) { TotalTime=time; }
  105. protected:
  106. StringClass Name;
  107. int TotalCalls;
  108. float TotalTime;
  109. WWProfileHierachyInfoClass * Parent;
  110. WWProfileHierachyInfoClass * Child;
  111. WWProfileHierachyInfoClass * Sibling;
  112. };
  113. /*
  114. ** An iterator to navigate through the tree
  115. */
  116. class WWProfileIterator
  117. {
  118. public:
  119. // Access all the children of the current parent
  120. void First(void);
  121. void Next(void);
  122. bool Is_Done(void);
  123. void Enter_Child( void ); // Make the current child the new parent
  124. void Enter_Child( int index ); // Make the given child the new parent
  125. void Enter_Parent( void ); // Make the current parent's parent the new parent
  126. // Access the current child
  127. const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
  128. int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
  129. float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
  130. // Access the current parent
  131. const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
  132. int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
  133. float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
  134. protected:
  135. WWProfileHierachyNodeClass * CurrentParent;
  136. WWProfileHierachyNodeClass * CurrentChild;
  137. WWProfileIterator( WWProfileHierachyNodeClass * start );
  138. friend class WWProfileManager;
  139. };
  140. /*
  141. ** An iterator to walk through the tree in depth first order
  142. */
  143. class WWProfileInOrderIterator
  144. {
  145. public:
  146. void First(void);
  147. void Next(void);
  148. bool Is_Done(void);
  149. // Access the current node
  150. const char * Get_Current_Name( void ) { return CurrentNode->Get_Name(); }
  151. int Get_Current_Total_Calls( void ) { return CurrentNode->Get_Total_Calls(); }
  152. float Get_Current_Total_Time( void ) { return CurrentNode->Get_Total_Time(); }
  153. protected:
  154. WWProfileHierachyNodeClass * CurrentNode;
  155. WWProfileInOrderIterator( void );
  156. friend class WWProfileManager;
  157. };
  158. /*
  159. ** The Manager for the WWProfile system
  160. */
  161. class WWProfileManager {
  162. public:
  163. WWINLINE static void Enable_Profile(bool enable) { IsProfileEnabled=enable; }
  164. WWINLINE static bool Is_Profile_Enabled() { return IsProfileEnabled; }
  165. static void Start_Profile( const char * name );
  166. static void Stop_Profile( void );
  167. static void Start_Root_Profile( const char * name );
  168. static void Stop_Root_Profile( void );
  169. static void Reset( void );
  170. static void Increment_Frame_Counter( void );
  171. static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
  172. static float Get_Time_Since_Reset( void );
  173. static WWProfileIterator * Get_Iterator( void );
  174. static void Release_Iterator( WWProfileIterator * iterator );
  175. static WWProfileInOrderIterator * Get_In_Order_Iterator( void );
  176. static void Release_In_Order_Iterator( WWProfileInOrderIterator * iterator );
  177. static WWProfileHierachyNodeClass * Get_Root( void ) { return &Root; }
  178. static void Begin_Collecting();
  179. static void End_Collecting(const char* filename);
  180. static void Load_Profile_Log(const char* filename, WWProfileHierachyInfoClass**& array, unsigned& count);
  181. private:
  182. static WWProfileHierachyNodeClass Root;
  183. static WWProfileHierachyNodeClass * CurrentNode;
  184. static WWProfileHierachyNodeClass * CurrentRootNode;
  185. static int FrameCounter;
  186. static __int64 ResetTime;
  187. static bool IsProfileEnabled;
  188. friend class WWProfileInOrderIterator;
  189. };
  190. /*
  191. ** WWProfileSampleClass is a simple way to profile a function's scope
  192. ** Use the WWPROFILE macro at the start of scope to time
  193. */
  194. class WWProfileSampleClass {
  195. bool IsRoot;
  196. bool Enabled;
  197. public:
  198. WWProfileSampleClass( const char * name, bool is_root ) : IsRoot(is_root), Enabled(WWProfileManager::Is_Profile_Enabled())
  199. {
  200. if (Enabled) {
  201. if (IsRoot) WWProfileManager::Start_Root_Profile( name );
  202. else WWProfileManager::Start_Profile( name );
  203. }
  204. }
  205. ~WWProfileSampleClass( void )
  206. {
  207. if (Enabled) {
  208. if (IsRoot) WWProfileManager::Stop_Root_Profile();
  209. else WWProfileManager::Stop_Profile();
  210. }
  211. }
  212. };
  213. #ifdef ENABLE_WWPROFILE
  214. #define WWPROFILE( name ) WWProfileSampleClass _wwprofile( name, false )
  215. #define WWROOTPROFILE( name ) WWProfileSampleClass _wwprofile( name, true )
  216. #else
  217. #define WWPROFILE( name )
  218. #define WWROOTPROFILE( name )
  219. #endif
  220. /*
  221. ** WWTimeIt is like WWProfile, but it doesn't save anything, it just times one routine, regardless of thread
  222. */
  223. class WWTimeItClass {
  224. public:
  225. WWTimeItClass( const char * name );
  226. ~WWTimeItClass( void );
  227. private:
  228. const char * Name;
  229. __int64 Time;
  230. };
  231. #ifdef ENABLE_WWPROFILE
  232. #define WWTIMEIT( name ) WWTimeItClass _wwtimeit( name )
  233. #else
  234. #define WWTIMEIT( name )
  235. #endif
  236. /*
  237. ** WWMeasureItClass is like WWTimeItClass, but it pokes the result into the given float,
  238. ** and can be used in the release build.
  239. */
  240. class WWMeasureItClass {
  241. public:
  242. WWMeasureItClass( float * p_result );
  243. ~WWMeasureItClass( void );
  244. private:
  245. __int64 Time;
  246. float * PResult;
  247. };
  248. // ----------------------------------------------------------------------------
  249. //
  250. // Use the first macro to log time and memory usage within the stack segment.
  251. // Use the second macro to log intermediate values. The intermediate values are
  252. // calculated from the previous intermediate log, so you can log how much each
  253. // item takes by placing the macro after each of the
  254. //
  255. // ----------------------------------------------------------------------------
  256. #ifdef ENABLE_TIME_AND_MEMORY_LOG
  257. #define WWLOG_PREPARE_TIME_AND_MEMORY(t) WWMemoryAndTimeLog memory_and_time_log(t)
  258. #define WWLOG_INTERMEDIATE(t) memory_and_time_log.Log_Intermediate(t)
  259. #else
  260. #define WWLOG_PREPARE_TIME_AND_MEMORY(t)
  261. #define WWLOG_INTERMEDIATE(t)
  262. #endif
  263. struct WWMemoryAndTimeLog
  264. {
  265. unsigned TimeStart;
  266. unsigned IntermediateTimeStart;
  267. int AllocCountStart;
  268. int IntermediateAllocCountStart;
  269. int AllocSizeStart;
  270. int IntermediateAllocSizeStart;
  271. StringClass Name;
  272. static unsigned TabCount;
  273. WWMemoryAndTimeLog(const char* name);
  274. ~WWMemoryAndTimeLog();
  275. void Log_Intermediate(const char* text);
  276. };
  277. #endif // WWPROFILE_H