ProfileMemory.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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_MEM
  7. class MemoryProfiler;
  8. struct ArenaMemoryData
  9. {
  10. size_t allocatedBytes; // memory allocated
  11. size_t alignmentBytes; // memory for alignment
  12. size_t requestBytes; // memory asked to be allocated
  13. size_t requestCount; // count of alloc
  14. size_t reuseBytes;
  15. size_t reuseCount;
  16. size_t freelistBytes; // memory asked to be freed.
  17. size_t freelistCount; // count of freed
  18. size_t resetCount;
  19. ArenaMemoryData * prev;
  20. ArenaMemoryData * next;
  21. MemoryProfiler * profiler;
  22. };
  23. struct ArenaMemoryDataSummary
  24. {
  25. size_t arenaCount;
  26. size_t outstandingCount;
  27. ArenaMemoryData total;
  28. ArenaMemoryData max;
  29. ArenaMemoryData * data;
  30. };
  31. struct PageMemoryData
  32. {
  33. size_t allocSegmentCount;
  34. size_t allocSegmentBytes;
  35. size_t releaseSegmentCount;
  36. size_t releaseSegmentBytes;
  37. size_t allocPageCount;
  38. size_t releasePageCount;
  39. size_t decommitPageCount;
  40. size_t recommitPageCount;
  41. size_t currentCommittedPageCount;
  42. size_t peakCommittedPageCount;
  43. };
  44. struct RecyclerMemoryData
  45. {
  46. size_t allocatedBytes;
  47. size_t alignmentBytes;
  48. size_t requestBytes;
  49. size_t requestCount;
  50. };
  51. class MemoryProfiler
  52. {
  53. public:
  54. MemoryProfiler();
  55. ~MemoryProfiler();
  56. static ArenaMemoryData * Begin(LPCWSTR name);
  57. static RecyclerMemoryData * GetRecyclerMemoryData();
  58. static PageMemoryData * GetPageMemoryData(PageAllocatorType type);
  59. static void Reset(LPCWSTR name, ArenaMemoryData * arena);
  60. static void End(LPCWSTR name, ArenaMemoryData * arena);
  61. static void PrintAll();
  62. static void PrintCurrentThread();
  63. static bool IsTraceEnabled(bool isRecycler = false);
  64. static bool IsEnabled();
  65. static bool DoTrackRecyclerAllocation();
  66. template<typename THandler>
  67. static void GetArenaMemoryUsage(THandler handler)
  68. {
  69. ForEachProfiler([&] (MemoryProfiler * memoryProfiler)
  70. {
  71. memoryProfiler->WithArenaUsageSummary(true, [&] (int count, _In_reads_(count) LPWSTR * name, _In_reads_(count) ArenaMemoryDataSummary * summaries)
  72. {
  73. for (int i = 0; i < count; i++)
  74. {
  75. ArenaMemoryDataSummary * data = summaries[i];
  76. if (data == nullptr)
  77. {
  78. continue;
  79. }
  80. handler(name[i], data);
  81. }
  82. });
  83. });
  84. }
  85. private:
  86. int CreateArenaUsageSummary(ArenaAllocator * alloc, bool liveOnly,
  87. _Outptr_result_buffer_(return) LPWSTR ** name_ptr, _Outptr_result_buffer_(return) ArenaMemoryDataSummary *** summaries_ptr);
  88. template<typename THandler>
  89. void WithArenaUsageSummary(bool liveOnly, THandler handler);
  90. template<typename THandler>
  91. static void ForEachProfiler(THandler handler)
  92. {
  93. MemoryProfiler * memoryProfiler = MemoryProfiler::profilers;
  94. while (memoryProfiler != nullptr)
  95. {
  96. handler(memoryProfiler);
  97. memoryProfiler = memoryProfiler->next;
  98. }
  99. }
  100. static MemoryProfiler * EnsureMemoryProfiler();
  101. static void AccumulateData(ArenaMemoryDataSummary *, ArenaMemoryData *, bool reset = false);
  102. void Print();
  103. void PrintArenaHeader(char16 const * title);
  104. static void PrintPageMemoryData(PageMemoryData const& pageMemoryData, char const * title);
  105. private:
  106. void PrintArena(bool liveOnly);
  107. static THREAD_LOCAL MemoryProfiler * Instance;
  108. static CriticalSection s_cs;
  109. static AutoPtr<MemoryProfiler, NoCheckHeapAllocator> profilers;
  110. PageAllocator pageAllocator;
  111. ArenaAllocator alloc;
  112. JsUtil::BaseDictionary<LPWSTR, ArenaMemoryDataSummary *, ArenaAllocator, PrimeSizePolicy> arenaDataMap;
  113. PageMemoryData pageMemoryData[PageAllocatorType_Max];
  114. RecyclerMemoryData recyclerMemoryData;
  115. MemoryProfiler * next;
  116. DWORD threadId;
  117. };
  118. template<typename THandler>
  119. void
  120. MemoryProfiler::WithArenaUsageSummary(bool liveOnly, THandler handler)
  121. {
  122. // This is debug only code, we don't care if we catch the right exception
  123. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(ExceptionType_DisableCheck);
  124. PageAllocator tempPageAlloc(nullptr, Js::Configuration::Global.flags);
  125. ArenaAllocator tempAlloc(_u("MemoryProfiler"), &tempPageAlloc, Js::Throw::OutOfMemory);
  126. LPWSTR * name = nullptr;
  127. ArenaMemoryDataSummary ** summaries = nullptr;
  128. int count = CreateArenaUsageSummary(&tempAlloc, liveOnly, &name, &summaries);
  129. handler(count, name, summaries);
  130. }
  131. #endif