heapprof.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*++
  2. Copyright (c) 2016 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. heapprof.c
  5. Abstract:
  6. This module implements Minoca specific heap profiling support.
  7. Author:
  8. Evan Green 2-Mar-2016
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "rtlp.h"
  16. #include <minoca/debug/spproto.h>
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. //
  21. // ------------------------------------------------------ Data Type Definitions
  22. //
  23. /*++
  24. Structure Description:
  25. This structure defines the context used to collect heap statistics when
  26. iterating through a heap's tree of heap tag statistics.
  27. Members:
  28. Buffer - Supplies a pointer to a buffer that is used to collect the heap's
  29. statistics for the profiler.
  30. BufferSize - Supplies the size of the buffer, in bytes.
  31. --*/
  32. typedef struct _HEAP_PROFILER_CONTEXT {
  33. PVOID Buffer;
  34. UINTN BufferSize;
  35. } HEAP_PROFILER_CONTEXT, *PHEAP_PROFILER_CONTEXT;
  36. //
  37. // ----------------------------------------------- Internal Function Prototypes
  38. //
  39. VOID
  40. RtlpGetProfilerMemoryHeapTagStatistic (
  41. PRED_BLACK_TREE Tree,
  42. PRED_BLACK_TREE_NODE Node,
  43. ULONG Level,
  44. PVOID Context
  45. );
  46. //
  47. // -------------------------------------------------------------------- Globals
  48. //
  49. //
  50. // ------------------------------------------------------------------ Functions
  51. //
  52. RTL_API
  53. VOID
  54. RtlHeapProfilerGetStatistics (
  55. PMEMORY_HEAP Heap,
  56. PVOID Buffer,
  57. ULONG BufferSize
  58. )
  59. /*++
  60. Routine Description:
  61. This routine fills the given buffer with the current heap statistics.
  62. Arguments:
  63. Heap - Supplies a pointer to the heap.
  64. Buffer - Supplies the buffer to fill with heap statistics.
  65. BufferSize - Supplies the size of the buffer.
  66. Return Value:
  67. None.
  68. --*/
  69. {
  70. HEAP_PROFILER_CONTEXT ProfilerContext;
  71. PPROFILER_MEMORY_POOL ProfilerHeap;
  72. //
  73. // Cast the start of the buffer as a pointer to a profiler heap.
  74. //
  75. ASSERT(BufferSize > sizeof(PROFILER_MEMORY_POOL));
  76. ProfilerHeap = (PPROFILER_MEMORY_POOL)Buffer;
  77. //
  78. // Re-package the basic heap statistics into the profiler's format, writing
  79. // to the buffer.
  80. //
  81. ProfilerHeap->Magic = PROFILER_POOL_MAGIC;
  82. ProfilerHeap->TagCount = Heap->TagStatistics.TagCount;
  83. ProfilerHeap->TotalPoolSize = Heap->Statistics.TotalHeapSize;
  84. ProfilerHeap->FreeListSize = Heap->Statistics.FreeListSize;
  85. ProfilerHeap->TotalAllocationCalls = Heap->Statistics.TotalAllocationCalls;
  86. ProfilerHeap->FailedAllocations = Heap->Statistics.FailedAllocations;
  87. ProfilerHeap->TotalFreeCalls = Heap->Statistics.TotalFreeCalls;
  88. //
  89. // Now get the statistics for each unique tag in the heap, filling in the
  90. // remainder of the supplied buffer.
  91. //
  92. ProfilerContext.Buffer = (PBYTE)Buffer + sizeof(PROFILER_MEMORY_POOL);
  93. ProfilerContext.BufferSize = BufferSize - sizeof(PROFILER_MEMORY_POOL);
  94. RtlRedBlackTreeIterate(&(Heap->TagStatistics.Tree),
  95. RtlpGetProfilerMemoryHeapTagStatistic,
  96. &ProfilerContext);
  97. return;
  98. }
  99. //
  100. // --------------------------------------------------------- Internal Functions
  101. //
  102. VOID
  103. RtlpGetProfilerMemoryHeapTagStatistic (
  104. PRED_BLACK_TREE Tree,
  105. PRED_BLACK_TREE_NODE Node,
  106. ULONG Level,
  107. PVOID Context
  108. )
  109. /*++
  110. Routine Description:
  111. This routine is called once for each node in the tree (via an in order
  112. traversal). It dumps the the statistics in the heap's profiler buffer.
  113. Arguments:
  114. Tree - Supplies a pointer to the tree being enumerated.
  115. Node - Supplies a pointer to the node.
  116. Level - Supplies the depth into the tree that this node exists at. 0 is
  117. the root.
  118. Context - Supplies an optional opaque pointer of context that was provided
  119. when the iteration was requested. In this case it supplies a context
  120. to be filled with heap tag data.
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. ULONG CopySize;
  126. PHEAP_PROFILER_CONTEXT ProfilerContext;
  127. PPROFILER_MEMORY_POOL_TAG_STATISTIC ProfilerStatistic;
  128. PMEMORY_HEAP_TAG_STATISTIC TagStatistic;
  129. ASSERT(Context != NULL);
  130. ProfilerContext = (PHEAP_PROFILER_CONTEXT)Context;
  131. CopySize = sizeof(PROFILER_MEMORY_POOL_TAG_STATISTIC);
  132. //
  133. // Cast the start of the heap's profiler buffer as a pointer to a profiler
  134. // tag statistic.
  135. //
  136. ASSERT(ProfilerContext->Buffer != NULL);
  137. ASSERT(ProfilerContext->BufferSize >= CopySize);
  138. ProfilerStatistic =
  139. (PPROFILER_MEMORY_POOL_TAG_STATISTIC)ProfilerContext->Buffer;
  140. //
  141. // Convert the memory heap tag statistics to that of the profiler.
  142. //
  143. TagStatistic = RED_BLACK_TREE_VALUE(Node, MEMORY_HEAP_TAG_STATISTIC, Node);
  144. ProfilerStatistic->Tag = TagStatistic->Tag;
  145. ProfilerStatistic->LargestAllocation = TagStatistic->LargestAllocation;
  146. ProfilerStatistic->ActiveSize = TagStatistic->ActiveSize;
  147. ProfilerStatistic->LargestActiveSize = TagStatistic->LargestActiveSize;
  148. ProfilerStatistic->LifetimeAllocationSize =
  149. TagStatistic->LifetimeAllocationSize;
  150. ProfilerStatistic->ActiveAllocationCount =
  151. TagStatistic->ActiveAllocationCount;
  152. ProfilerStatistic->LargestActiveAllocationCount =
  153. TagStatistic->LargestActiveAllocationCount;
  154. //
  155. // Move the profiler buffer forward and decrease the size.
  156. //
  157. ProfilerContext->Buffer = (PBYTE)ProfilerContext->Buffer + CopySize;
  158. ProfilerContext->BufferSize -= CopySize;
  159. return;
  160. }