profiler.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _PROFILER_H_
  23. #define _PROFILER_H_
  24. #ifndef _TORQUECONFIG_H_
  25. #include "torqueConfig.h"
  26. #endif
  27. #ifdef TORQUE_ENABLE_PROFILER
  28. struct ProfilerData;
  29. struct ProfilerRootData;
  30. /// The Profiler is used to see how long a specific chunk of code takes to execute.
  31. /// All values outputted by the profiler are percentages of the time that it takes
  32. /// to run entire main loop.
  33. ///
  34. /// First, you must #define TORQUE_ENABLE_PROFILER in profiler.h in order to
  35. /// active it. Examples of script use:
  36. /// @code
  37. /// //enables or disables profiling. Data is only gathered when the profiler is enabled.
  38. /// profilerEnable(bool enable);
  39. /// profilerReset(); //resets the data gathered by the profiler
  40. /// profilerDump(); //dumps all profiler data to the console
  41. /// profilerDumpToFile(string filename); //dumps all profiler data to a given file
  42. /// profilerMarkerEnable((string markerName, bool enable); //enables or disables a given profile tag
  43. /// @endcode
  44. ///
  45. /// The C++ code side of the profiler uses pairs of PROFILE_START() and PROFILE_END().
  46. ///
  47. /// When using these macros, make sure there is a PROFILE_END() for every PROFILE_START
  48. /// and a PROFILE_START() for every PROFILE_END(). It is fine to nest these macros, however,
  49. /// you must make sure that no matter what execution path the code takes, the PROFILE macros
  50. /// will be balanced.
  51. ///
  52. /// The profiler can be used to locate areas of code that are slow or should be considered for
  53. /// optimization. Since it tracks the relative time of execution of that code to the execution
  54. /// of the main loop, it is possible to benchmark any given code to see if changes made will
  55. /// actually improve performance.
  56. ///
  57. /// Here are some examples:
  58. /// @code
  59. /// PROFILE_START(TerrainRender);
  60. /// //some code here
  61. /// PROFILE_START(TerrainRenderGridSquare);
  62. /// //some code here
  63. /// PROFILE_END();
  64. /// //possibly some code here
  65. /// PROFILE_END();
  66. /// @endcode
  67. class Profiler
  68. {
  69. enum {
  70. MaxStackDepth = 256,
  71. DumpFileNameLength = 256
  72. };
  73. U32 mCurrentHash;
  74. ProfilerData *mCurrentProfilerData;
  75. ProfilerData *mProfileList;
  76. ProfilerData *mRootProfilerData;
  77. bool mEnabled;
  78. S32 mStackDepth;
  79. bool mNextEnable;
  80. U32 mMaxStackDepth;
  81. bool mDumpToConsole;
  82. bool mDumpToFile;
  83. char mDumpFileName[DumpFileNameLength];
  84. void dump();
  85. void validate();
  86. public:
  87. Profiler();
  88. ~Profiler();
  89. /// Reset the data in the profiler
  90. void reset();
  91. /// Dumps the profile to console
  92. void dumpToConsole();
  93. /// Dumps the profile data to a file
  94. /// @param fileName filename to dump data to
  95. void dumpToFile(const char *fileName);
  96. /// Enable profiling
  97. void enable(bool enabled);
  98. bool isEnabled() { return mNextEnable; }
  99. /// Helper function for macro definition PROFILE_START
  100. void hashPush(ProfilerRootData *data);
  101. /// Helper function for macro definition PROFILE_END
  102. void hashPop(ProfilerRootData *expected=NULL);
  103. /// Enable a profiler marker
  104. void enableMarker(const char *marker, bool enabled);
  105. #ifdef TORQUE_ENABLE_PROFILE_PATH
  106. /// Get current profile path
  107. const char * getProfilePath();
  108. /// Construct profile path of given profiler data
  109. const char * constructProfilePath(ProfilerData * pd);
  110. #endif
  111. };
  112. extern Profiler *gProfiler;
  113. struct ProfilerRootData
  114. {
  115. const char *mName;
  116. U32 mNameHash;
  117. ProfilerData *mFirstProfilerData;
  118. ProfilerRootData *mNextRoot;
  119. F64 mTotalTime;
  120. F64 mSubTime;
  121. U32 mTotalInvokeCount;
  122. bool mEnabled;
  123. static ProfilerRootData *sRootList;
  124. ProfilerRootData(const char *name);
  125. };
  126. struct ProfilerData
  127. {
  128. ProfilerRootData *mRoot; ///< link to root node.
  129. ProfilerData *mNextForRoot; ///< links together all ProfilerData's for a particular root
  130. ProfilerData *mNextProfilerData; ///< links all the profilerDatas
  131. ProfilerData *mNextHash;
  132. ProfilerData *mParent;
  133. ProfilerData *mNextSibling;
  134. ProfilerData *mFirstChild;
  135. enum {
  136. HashTableSize = 32,
  137. };
  138. ProfilerData *mChildHash[HashTableSize];
  139. ProfilerData *mLastSeenProfiler;
  140. U32 mHash;
  141. U32 mSubDepth;
  142. U32 mInvokeCount;
  143. U64 mStartTime;
  144. F64 mTotalTime;
  145. F64 mSubTime;
  146. #ifdef TORQUE_ENABLE_PROFILE_PATH
  147. const char * mPath;
  148. #endif
  149. };
  150. #define PROFILE_START(name) \
  151. static ProfilerRootData pdata##name##obj (#name); \
  152. if(gProfiler) gProfiler->hashPush(& pdata##name##obj )
  153. #define PROFILE_END() if(gProfiler) gProfiler->hashPop()
  154. #define PROFILE_END_NAMED(name) if(gProfiler) gProfiler->hashPop(& pdata##name##obj)
  155. class ScopedProfiler {
  156. public:
  157. ScopedProfiler(ProfilerRootData *data) {
  158. if (gProfiler) gProfiler->hashPush(data);
  159. }
  160. ~ScopedProfiler() {
  161. if (gProfiler) gProfiler->hashPop();
  162. }
  163. };
  164. #define PROFILE_SCOPE(name) \
  165. static ProfilerRootData pdata##name##obj (#name); \
  166. ScopedProfiler scopedProfiler##name##obj(&pdata##name##obj);
  167. #else
  168. #define PROFILE_START(x)
  169. #define PROFILE_END()
  170. #define PROFILE_SCOPE(x)
  171. #define PROFILE_END_NAMED(x)
  172. #endif
  173. #endif