profiler.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 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. #include "torqueConfig.h"
  25. #ifdef TORQUE_ENABLE_PROFILER
  26. struct ProfilerData;
  27. struct ProfilerRootData;
  28. /// The Profiler is used to see how long a specific chunk of code takes to execute.
  29. /// All values outputted by the profiler are percentages of the time that it takes
  30. /// to run entire main loop.
  31. ///
  32. /// Examples of script use:
  33. /// @code
  34. /// //enables or disables profiling. Data is only gathered when the profiler is enabled.
  35. /// profilerEnable(bool enable);
  36. /// profilerReset(); //resets the data gathered by the profiler
  37. /// profilerDump(); //dumps all profiler data to the console
  38. /// profilerDumpToFile(string filename); //dumps all profiler data to a given file
  39. /// profilerMarkerEnable((string markerName, bool enable); //enables or disables a given profile tag
  40. /// @endcode
  41. ///
  42. /// The C++ code side of the profiler uses pairs of PROFILE_START() and PROFILE_END().
  43. ///
  44. /// When using these macros, make sure there is a PROFILE_END() for every PROFILE_START
  45. /// and a PROFILE_START() for every PROFILE_END(). It is fine to nest these macros, however,
  46. /// you must make sure that no matter what execution path the code takes, the PROFILE macros
  47. /// will be balanced.
  48. ///
  49. /// The profiler can be used to locate areas of code that are slow or should be considered for
  50. /// optimization. Since it tracks the relative time of execution of that code to the execution
  51. /// of the main loop, it is possible to benchmark any given code to see if changes made will
  52. /// actually improve performance.
  53. ///
  54. /// Here are some examples:
  55. /// @code
  56. /// PROFILE_START(TerrainRender);
  57. /// //some code here
  58. /// PROFILE_START(TerrainRenderGridSquare);
  59. /// //some code here
  60. /// PROFILE_END();
  61. /// //possibly some code here
  62. /// PROFILE_END();
  63. /// @endcode
  64. class Profiler
  65. {
  66. enum {
  67. MaxStackDepth = 256,
  68. DumpFileNameLength = 256
  69. };
  70. U32 mCurrentHash;
  71. ProfilerData *mCurrentProfilerData;
  72. ProfilerData *mProfileList;
  73. ProfilerData *mRootProfilerData;
  74. bool mEnabled;
  75. S32 mStackDepth;
  76. bool mNextEnable;
  77. U32 mMaxStackDepth;
  78. bool mDumpToConsole;
  79. bool mDumpToFile;
  80. char mDumpFileName[DumpFileNameLength];
  81. void dump();
  82. void validate();
  83. public:
  84. Profiler();
  85. ~Profiler();
  86. /// Reset the data in the profiler
  87. void reset();
  88. /// Dumps the profile to console
  89. void dumpToConsole();
  90. /// Dumps the profile data to a file
  91. /// @param fileName filename to dump data to
  92. void dumpToFile(const char *fileName);
  93. /// Enable profiling
  94. void enable(bool enabled);
  95. /// Helper function for macro definition PROFILE_START
  96. void hashPush(ProfilerRootData *data);
  97. /// Helper function for macro definition PROFILE_END
  98. void hashPop();
  99. /// Enable a profiler marker
  100. void enableMarker(const char *marker, bool enabled);
  101. };
  102. extern Profiler *gProfiler;
  103. struct ProfilerRootData
  104. {
  105. const char *mName;
  106. U32 mNameHash;
  107. ProfilerData *mFirstProfilerData;
  108. ProfilerRootData *mNextRoot;
  109. F64 mTotalTime;
  110. F64 mSubTime;
  111. U32 mTotalInvokeCount;
  112. bool mEnabled;
  113. static ProfilerRootData *sRootList;
  114. ProfilerRootData(const char *name);
  115. };
  116. struct ProfilerData
  117. {
  118. ProfilerRootData *mRoot; ///< link to root node.
  119. ProfilerData *mNextForRoot; ///< links together all ProfilerData's for a particular root
  120. ProfilerData *mNextProfilerData; ///< links all the profilerDatas
  121. ProfilerData *mNextHash;
  122. ProfilerData *mParent;
  123. ProfilerData *mNextSibling;
  124. ProfilerData *mFirstChild;
  125. enum {
  126. HashTableSize = 32,
  127. };
  128. ProfilerData *mChildHash[HashTableSize];
  129. ProfilerData *mLastSeenProfiler;
  130. U32 mHash;
  131. U32 mSubDepth;
  132. U32 mInvokeCount;
  133. U32 mStartTime[2];
  134. F64 mTotalTime;
  135. F64 mSubTime;
  136. };
  137. #undef PROFILE_START
  138. #define PROFILE_START(name) \
  139. static ProfilerRootData pdata##name##obj (#name); \
  140. if(gProfiler) gProfiler->hashPush(& pdata##name##obj )
  141. #undef PROFILE_END
  142. #define PROFILE_END() if(gProfiler) gProfiler->hashPop()
  143. class ScopedProfiler {
  144. public:
  145. ScopedProfiler(ProfilerRootData *data) {
  146. if (gProfiler) gProfiler->hashPush(data);
  147. }
  148. ~ScopedProfiler() {
  149. if (gProfiler) gProfiler->hashPop();
  150. }
  151. };
  152. #undef PROFILE_SCOPE
  153. #define PROFILE_SCOPE(name) \
  154. static ProfilerRootData pdata##name##obj (#name); \
  155. ScopedProfiler scopedProfiler##name##obj(&pdata##name##obj);
  156. #endif
  157. #endif