ProfileInstrument.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #ifdef PROFILE_EXEC
  7. #include "DataStructures/FixedStack.h"
  8. #include "DataStructures/Tree.h"
  9. namespace Js
  10. {
  11. //
  12. // Type of each timestamp.
  13. //
  14. typedef long long TimeStamp;
  15. ///----------------------------------------------------------------------------
  16. ///----------------------------------------------------------------------------
  17. ///
  18. /// struct TimeEntry
  19. ///
  20. /// Simple pair of (tag, timestamp).
  21. ///
  22. ///----------------------------------------------------------------------------
  23. ///----------------------------------------------------------------------------
  24. struct TimeEntry
  25. {
  26. Phase tag;
  27. TimeStamp time;
  28. explicit TimeEntry(Phase profileTag = InvalidPhase, TimeStamp curTime = 0) :
  29. tag(profileTag),
  30. time(curTime)
  31. {}
  32. };
  33. ///----------------------------------------------------------------------------
  34. ///----------------------------------------------------------------------------
  35. ///
  36. /// struct UnitData
  37. ///
  38. /// Stores the elemental data for individual calls. Accumulates the inclusive,
  39. /// exclusive sums, count, and maximum.
  40. ///
  41. ///----------------------------------------------------------------------------
  42. ///----------------------------------------------------------------------------
  43. struct UnitData
  44. {
  45. // Data
  46. public:
  47. uint count;
  48. TimeStamp incl;
  49. TimeStamp excl;
  50. TimeStamp max;
  51. // Constructor
  52. public:
  53. UnitData();
  54. // Methods
  55. public:
  56. void Add(TimeStamp, TimeStamp);
  57. };
  58. ///----------------------------------------------------------------------------
  59. ///----------------------------------------------------------------------------
  60. ///
  61. /// class Profiler
  62. ///
  63. ///----------------------------------------------------------------------------
  64. ///----------------------------------------------------------------------------
  65. class Profiler
  66. {
  67. friend class ScriptContextProfiler;
  68. // Local types
  69. private:
  70. typedef TreeNode<UnitData, PhaseCount> TypeNode;
  71. // Data
  72. private:
  73. //
  74. // Maximum depth of the stack. This should be some safe limit
  75. //
  76. static const int MaxStackDepth = 20;
  77. //
  78. // Controls the scale of the measuring clock. a value of 1000 indicates
  79. // millisecond, 1000,000 implies micro-seconds.
  80. //
  81. static const int FrequencyScale = 1000;
  82. //
  83. // Used for printing the report
  84. //
  85. static const int TabWidth = 1;
  86. static const int PhaseNameWidth = 27;
  87. FixedStack<TimeEntry, MaxStackDepth>
  88. timeStack;
  89. TimeStamp inclSumAtLevel[PhaseCount];
  90. TypeNode rootNode;
  91. TypeNode *curNode;
  92. ArenaAllocator *alloc;
  93. // Constructor
  94. public:
  95. Profiler(ArenaAllocator *alloc);
  96. // Implementation
  97. private:
  98. static TimeStamp GetTime();
  99. static TimeStamp GetFrequency();
  100. template<class FVisit>
  101. static void ForEachNode(Phase tag, TypeNode *curNode, FVisit visit, Phase parentTag = InvalidPhase);
  102. void Push(TimeEntry entry);
  103. void Pop(TimeEntry entry);
  104. void PrintTree(TypeNode *curNode, TypeNode *baseNode, int, TimeStamp freq);
  105. void MergeTree(TypeNode *toNode, TypeNode *fromNode);
  106. // Methods
  107. public:
  108. class SuspendRecord
  109. {
  110. private:
  111. Phase phase[MaxStackDepth];
  112. uint count;
  113. friend class Profiler;
  114. };
  115. void Begin(Phase tag);
  116. void End(Phase tag);
  117. void EndAllUpTo(Phase tag);
  118. void Print(Phase baseTag);
  119. void Merge(Profiler * profiler);
  120. void Suspend(Phase tag, SuspendRecord * suspendRecord);
  121. void Resume(SuspendRecord * suspendRecord);
  122. };
  123. } //namespace Js
  124. #define ASYNC_HOST_OPERATION_START(threadContext) {Js::Profiler::SuspendRecord __suspendRecord; bool wasInAsync = threadContext->AsyncHostOperationStart(&__suspendRecord)
  125. #define ASYNC_HOST_OPERATION_END(threadContext) threadContext->AsyncHostOperationEnd(wasInAsync, &__suspendRecord); }
  126. #elif DBG
  127. #define ASYNC_HOST_OPERATION_START(threadContext) { bool wasInAsync = threadContext->AsyncHostOperationStart(nullptr)
  128. #define ASYNC_HOST_OPERATION_END(threadContext) threadContext->AsyncHostOperationEnd(wasInAsync, nullptr); }
  129. #else
  130. #define ASYNC_HOST_OPERATION_START(threadContext)
  131. #define ASYNC_HOST_OPERATION_END(threadContext)
  132. #endif