RecyclerTelemetryInfo.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. #include "CommonDefines.h"
  7. #include "CollectionFlags.h"
  8. #include "RecyclerWaitReason.h"
  9. #include "Common/Tick.h"
  10. #include "AllocatorTelemetryStats.h"
  11. #include "HeapBucketStats.h"
  12. #include "DataStructures/SList.h"
  13. #ifdef ENABLE_BASIC_TELEMETRY
  14. #include "Windows.h"
  15. #endif
  16. namespace Memory
  17. {
  18. class Recycler;
  19. class IdleDecommitPageAllocator;
  20. class RecyclerTelemetryInfo;
  21. // struct that defines an interface with host on how we can get key data stats
  22. class RecyclerTelemetryHostInterface
  23. {
  24. public:
  25. virtual LPFILETIME GetLastScriptExecutionEndTime() const = 0;
  26. virtual bool TransmitGCTelemetryStats(RecyclerTelemetryInfo& rti) = 0;
  27. virtual bool TransmitTelemetryError(const RecyclerTelemetryInfo& rti, const char* msg) = 0;
  28. virtual bool TransmitHeapUsage(size_t totalHeapBytes, size_t usedHeapBytes, double heapUsedRatio) = 0;
  29. virtual bool IsTelemetryProviderEnabled() const = 0;
  30. virtual bool IsThreadBound() const = 0;
  31. virtual DWORD GetCurrentScriptThreadID() const = 0;
  32. virtual uint GetClosedContextCount() const = 0;
  33. };
  34. #ifdef ENABLE_BASIC_TELEMETRY
  35. /**
  36. * struct with all data we want to capture for a specific GC pass.
  37. *
  38. * This forms a linked list, one for each per-stats pass.
  39. * The last element in the list points to the head instead of nullptr.
  40. */
  41. struct RecyclerTelemetryGCPassStats
  42. {
  43. FILETIME passStartTimeFileTime;
  44. CollectionState startPassCollectionState;
  45. CollectionState endPassCollectionState;
  46. ETWEventGCActivationTrigger collectionStartReason;
  47. ETWEventGCActivationTrigger collectionFinishReason;
  48. CollectionFlags collectionStartFlags;
  49. Js::Tick passStartTimeTick;
  50. Js::Tick passEndTimeTick;
  51. Js::TickDelta startPassProcessingElapsedTime;
  52. Js::TickDelta endPassProcessingElapsedTime;
  53. Js::TickDelta computeBucketStatsElapsedTime;
  54. FILETIME lastScriptExecutionEndTime;
  55. Js::TickDelta uiThreadBlockedTimes[static_cast<size_t>(RecyclerWaitReason::Other) + 1];
  56. uint64 uiThreadBlockedCpuTimesUser[static_cast<size_t>(RecyclerWaitReason::Other) + 1];
  57. uint64 uiThreadBlockedCpuTimesKernel[static_cast<size_t>(RecyclerWaitReason::Other) + 1];
  58. bool isInScript;
  59. bool isScriptActive;
  60. bool isGCPassActive;
  61. uint closedContextCount;
  62. uint pinnedObjectCount;
  63. size_t processAllocaterUsedBytes_start;
  64. size_t processAllocaterUsedBytes_end;
  65. size_t processCommittedBytes_start;
  66. size_t processCommittedBytes_end;
  67. HeapBucketStats bucketStats;
  68. AllocatorSizes threadPageAllocator_start;
  69. AllocatorSizes threadPageAllocator_end;
  70. AllocatorSizes recyclerLeafPageAllocator_start;
  71. AllocatorSizes recyclerLeafPageAllocator_end;
  72. AllocatorSizes recyclerLargeBlockPageAllocator_start;
  73. AllocatorSizes recyclerLargeBlockPageAllocator_end;
  74. #ifdef RECYCLER_WRITE_BARRIER_ALLOC_SEPARATE_PAGE
  75. AllocatorSizes recyclerWithBarrierPageAllocator_start;
  76. AllocatorSizes recyclerWithBarrierPageAllocator_end;
  77. #endif
  78. };
  79. /**
  80. * Consolidated summary of data from RecyclerFlagsTable that we want to
  81. * transmit via telemetry. Goal is to pack this into maximum of 64-bits.
  82. */
  83. enum RecyclerFlagsTableSummary : uint32
  84. {
  85. None = 0x0000,
  86. IsMemProtectMode = 0x0001,
  87. IsConcurrentEnabled = 0x0002,
  88. EnableScanInteriorPointers = 0x0004,
  89. EnableScanImplicitRoots = 0x0008,
  90. DisableCollectOnAllocationHeuristics = 0x0016,
  91. RecyclerStress = 0x0032,
  92. RecyclerBackgroundStress = 0x0064,
  93. RecyclerConcurrentStress = 0x0128,
  94. RecyclerConcurrentRepeatStress = 0x0256,
  95. RecyclerPartialStress = 0x0512,
  96. };
  97. typedef SList<RecyclerTelemetryGCPassStats, HeapAllocator> GCPassStatsList;
  98. /**
  99. *
  100. */
  101. class RecyclerTelemetryInfo
  102. {
  103. public:
  104. RecyclerTelemetryInfo(Recycler* recycler, RecyclerTelemetryHostInterface* hostInterface);
  105. ~RecyclerTelemetryInfo();
  106. void StartPass(CollectionState collectionState);
  107. void EndPass(CollectionState collectionState);
  108. void IncrementUserThreadBlockedCount(Js::TickDelta waitTime, RecyclerWaitReason source);
  109. void IncrementUserThreadBlockedCpuTimeUser(uint64 userMicroseconds, RecyclerWaitReason caller);
  110. void IncrementUserThreadBlockedCpuTimeKernel(uint64 kernelMicroseconds, RecyclerWaitReason caller);
  111. inline const Js::Tick& GetRecyclerStartTime() const { return this->recyclerStartTime; }
  112. RecyclerTelemetryGCPassStats* GetLastPassStats() const;
  113. inline const Js::Tick& GetLastTransmitTime() const { return this->lastTransmitTime; }
  114. inline const uint16 GetPassCount() const { return this->passCount; }
  115. const GUID& GetRecyclerID() const;
  116. bool IsOnScriptThread() const;
  117. GCPassStatsList::Iterator GetGCPassStatsIterator() const;
  118. RecyclerFlagsTableSummary GetRecyclerConfigFlags() const;
  119. AllocatorDecommitStats* GetThreadPageAllocator_decommitStats() { return &this->threadPageAllocator_decommitStats; }
  120. AllocatorDecommitStats* GetRecyclerLeafPageAllocator_decommitStats() { return &this->recyclerLeafPageAllocator_decommitStats; }
  121. AllocatorDecommitStats* GetRecyclerLargeBlockPageAllocator_decommitStats() { return &this->recyclerLargeBlockPageAllocator_decommitStats; }
  122. #ifdef RECYCLER_WRITE_BARRIER_ALLOC_SEPARATE_PAGE
  123. AllocatorDecommitStats* GetRecyclerWithBarrierPageAllocator_decommitStats() { return &this->recyclerWithBarrierPageAllocator_decommitStats; }
  124. #endif
  125. bool ShouldStartTelemetryCapture() const;
  126. private:
  127. Recycler* recycler;
  128. DWORD mainThreadID;
  129. RecyclerTelemetryHostInterface * hostInterface;
  130. Js::Tick recyclerStartTime;
  131. bool inPassActiveState;
  132. GCPassStatsList gcPassStats;
  133. Js::Tick lastTransmitTime;
  134. uint16 passCount;
  135. uint16 perfTrackPassCount;
  136. bool abortTelemetryCapture;
  137. AllocatorDecommitStats threadPageAllocator_decommitStats;
  138. AllocatorDecommitStats recyclerLeafPageAllocator_decommitStats;
  139. AllocatorDecommitStats recyclerLargeBlockPageAllocator_decommitStats;
  140. #ifdef RECYCLER_WRITE_BARRIER_ALLOC_SEPARATE_PAGE
  141. AllocatorDecommitStats recyclerWithBarrierPageAllocator_decommitStats;
  142. #endif
  143. bool ShouldTransmitGCStats() const;
  144. void FreeGCPassStats();
  145. void Reset();
  146. void FillInSizeData(IdleDecommitPageAllocator* allocator, AllocatorSizes* sizes) const;
  147. void ResetPerfTrackCounts();
  148. bool ShouldTransmitPerfTrackEvents() const;
  149. static size_t GetProcessCommittedBytes();
  150. };
  151. #else
  152. class RecyclerTelemetryInfo
  153. {
  154. };
  155. #endif // #ifdef ENABLE_BASIC_TELEMETRY
  156. }