PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/services/resource_coordinator/memory_instrumentation/graph_processor.h

http://github.com/chromium/chromium
C Header | 231 lines | 52 code | 27 blank | 152 comment | 0 complexity | 2243c1ea1da6a51fa829202c1b1455dc MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, BSD-2-Clause, LGPL-2.1, MPL-2.0, 0BSD, EPL-1.0, MPL-2.0-no-copyleft-exception, GPL-2.0, BitTorrent-1.0, CPL-1.0, LGPL-3.0, Unlicense, BSD-3-Clause, CC0-1.0, JSON, MIT, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_GRAPH_PROCESSOR_H_
  5. #define SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_GRAPH_PROCESSOR_H_
  6. #include <memory>
  7. #include "base/process/process_handle.h"
  8. #include "base/trace_event/process_memory_dump.h"
  9. #include "services/resource_coordinator/memory_instrumentation/graph.h"
  10. namespace memory_instrumentation {
  11. class GraphProcessor {
  12. public:
  13. // This map does not own the pointers inside.
  14. using MemoryDumpMap =
  15. std::map<base::ProcessId, const base::trace_event::ProcessMemoryDump*>;
  16. static std::unique_ptr<GlobalDumpGraph> CreateMemoryGraph(
  17. const MemoryDumpMap& process_dumps);
  18. static void RemoveWeakNodesFromGraph(GlobalDumpGraph* global_graph);
  19. static void AddOverheadsAndPropogateEntries(GlobalDumpGraph* global_graph);
  20. static void CalculateSizesForGraph(GlobalDumpGraph* global_graph);
  21. static std::map<base::ProcessId, uint64_t> ComputeSharedFootprintFromGraph(
  22. const GlobalDumpGraph& global_graph);
  23. private:
  24. friend class GraphProcessorTest;
  25. static void CollectAllocatorDumps(
  26. const base::trace_event::ProcessMemoryDump& source,
  27. GlobalDumpGraph* global_graph,
  28. GlobalDumpGraph::Process* process_graph);
  29. static void AddEdges(const base::trace_event::ProcessMemoryDump& source,
  30. GlobalDumpGraph* global_graph);
  31. static void MarkImplicitWeakParentsRecursively(GlobalDumpGraph::Node* node);
  32. static void MarkWeakOwnersAndChildrenRecursively(
  33. GlobalDumpGraph::Node* node,
  34. std::set<const GlobalDumpGraph::Node*>* nodes);
  35. static void RemoveWeakNodesRecursively(GlobalDumpGraph::Node* parent);
  36. static void AssignTracingOverhead(base::StringPiece allocator,
  37. GlobalDumpGraph* global_graph,
  38. GlobalDumpGraph::Process* process);
  39. static GlobalDumpGraph::Node::Entry AggregateNumericWithNameForNode(
  40. GlobalDumpGraph::Node* node,
  41. base::StringPiece name);
  42. static void AggregateNumericsRecursively(GlobalDumpGraph::Node* node);
  43. static void PropagateNumericsAndDiagnosticsRecursively(
  44. GlobalDumpGraph::Node* node);
  45. static base::Optional<uint64_t> AggregateSizeForDescendantNode(
  46. GlobalDumpGraph::Node* root,
  47. GlobalDumpGraph::Node* descendant);
  48. static void CalculateSizeForNode(GlobalDumpGraph::Node* node);
  49. /**
  50. * Calculate not-owned and not-owning sub-sizes of a memory allocator dump
  51. * from its children's (sub-)sizes.
  52. *
  53. * Not-owned sub-size refers to the aggregated memory of all children which
  54. * is not owned by other MADs. Conversely, not-owning sub-size is the
  55. * aggregated memory of all children which do not own another MAD. The
  56. * diagram below illustrates these two concepts:
  57. *
  58. * ROOT 1 ROOT 2
  59. * size: 4 size: 5
  60. * not-owned sub-size: 4 not-owned sub-size: 1 (!)
  61. * not-owning sub-size: 0 (!) not-owning sub-size: 5
  62. *
  63. * ^ ^
  64. * | |
  65. *
  66. * PARENT 1 ===== owns =====> PARENT 2
  67. * size: 4 size: 5
  68. * not-owned sub-size: 4 not-owned sub-size: 5
  69. * not-owning sub-size: 4 not-owning sub-size: 5
  70. *
  71. * ^ ^
  72. * | |
  73. *
  74. * CHILD 1 CHILD 2
  75. * size [given]: 4 size [given]: 5
  76. * not-owned sub-size: 4 not-owned sub-size: 5
  77. * not-owning sub-size: 4 not-owning sub-size: 5
  78. *
  79. * This method assumes that (1) the size of the dump, its children, and its
  80. * owners [see calculateSizes()] and (2) the not-owned and not-owning
  81. * sub-sizes of both the children and owners of the dump have already been
  82. * calculated [depth-first post-order traversal].
  83. */
  84. static void CalculateDumpSubSizes(GlobalDumpGraph::Node* node);
  85. /**
  86. * Calculate owned and owning coefficients of a memory allocator dump and
  87. * its owners.
  88. *
  89. * The owning coefficient refers to the proportion of a dump's not-owning
  90. * sub-size which is attributed to the dump (only relevant to owning MADs).
  91. * Conversely, the owned coefficient is the proportion of a dump's
  92. * not-owned sub-size, which is attributed to it (only relevant to owned
  93. * MADs).
  94. *
  95. * The not-owned size of the owned dump is split among its owners in the
  96. * order of the ownership importance as demonstrated by the following
  97. * example:
  98. *
  99. * memory allocator dumps
  100. * OWNED OWNER1 OWNER2 OWNER3 OWNER4
  101. * not-owned sub-size [given] 10 - - - -
  102. * not-owning sub-size [given] - 6 7 5 8
  103. * importance [given] - 2 2 1 0
  104. * attributed not-owned sub-size 2 - - - -
  105. * attributed not-owning sub-size - 3 4 0 1
  106. * owned coefficient 2/10 - - - -
  107. * owning coefficient - 3/6 4/7 0/5 1/8
  108. *
  109. * Explanation: Firstly, 6 bytes are split equally among OWNER1 and OWNER2
  110. * (highest importance). OWNER2 owns one more byte, so its attributed
  111. * not-owning sub-size is 6/2 + 1 = 4 bytes. OWNER3 is attributed no size
  112. * because it is smaller than the owners with higher priority. However,
  113. * OWNER4 is larger, so it's attributed the difference 8 - 7 = 1 byte.
  114. * Finally, 2 bytes remain unattributed and are hence kept in the OWNED
  115. * dump as attributed not-owned sub-size. The coefficients are then
  116. * directly calculated as fractions of the sub-sizes and corresponding
  117. * attributed sub-sizes.
  118. *
  119. * Note that we always assume that all ownerships of a dump overlap (e.g.
  120. * OWNER3 is subsumed by both OWNER1 and OWNER2). Hence, the table could
  121. * be alternatively represented as follows:
  122. *
  123. * owned memory range
  124. * 0 1 2 3 4 5 6 7 8 9 10
  125. * Priority 2 | OWNER1 + OWNER2 (split) | OWNER2 |
  126. * Priority 1 | (already attributed) |
  127. * Priority 0 | - - - (already attributed) - - - | OWNER4 |
  128. * Remainder | - - - - - (already attributed) - - - - - - | OWNED |
  129. *
  130. * This method assumes that (1) the size of the dump [see calculateSizes()]
  131. * and (2) the not-owned size of the dump and not-owning sub-sizes of its
  132. * owners [see the first step of calculateEffectiveSizes()] have already
  133. * been calculated. Note that the method doesn't make any assumptions about
  134. * the order in which dumps are visited.
  135. */
  136. static void CalculateDumpOwnershipCoefficient(GlobalDumpGraph::Node* node);
  137. /**
  138. * Calculate cumulative owned and owning coefficients of a memory allocator
  139. * dump from its (non-cumulative) owned and owning coefficients and the
  140. * cumulative coefficients of its parent and/or owned dump.
  141. *
  142. * The cumulative coefficients represent the total effect of all
  143. * (non-strict) ancestor ownerships on a memory allocator dump. The
  144. * cumulative owned coefficient of a MAD can be calculated simply as:
  145. *
  146. * cumulativeOwnedC(M) = ownedC(M) * cumulativeOwnedC(parent(M))
  147. *
  148. * This reflects the assumption that if a parent of a child MAD is
  149. * (partially) owned, then the parent's owner also indirectly owns (a part
  150. * of) the child MAD.
  151. *
  152. * The cumulative owning coefficient of a MAD depends on whether the MAD
  153. * owns another dump:
  154. *
  155. * [if M doesn't own another MAD]
  156. * / cumulativeOwningC(parent(M))
  157. * cumulativeOwningC(M) =
  158. * \ [if M owns another MAD]
  159. * owningC(M) * cumulativeOwningC(owned(M))
  160. *
  161. * The reasoning behind the first case is similar to the one for cumulative
  162. * owned coefficient above. The only difference is that we don't need to
  163. * include the dump's (non-cumulative) owning coefficient because it is
  164. * implicitly 1.
  165. *
  166. * The formula for the second case is derived as follows: Since the MAD
  167. * owns another dump, its memory is not included in its parent's not-owning
  168. * sub-size and hence shouldn't be affected by the parent's corresponding
  169. * cumulative coefficient. Instead, the MAD indirectly owns everything
  170. * owned by its owned dump (and so it should be affected by the
  171. * corresponding coefficient).
  172. *
  173. * Note that undefined coefficients (and coefficients of non-existent
  174. * dumps) are implicitly assumed to be 1.
  175. *
  176. * This method assumes that (1) the size of the dump [see calculateSizes()],
  177. * (2) the (non-cumulative) owned and owning coefficients of the dump [see
  178. * the second step of calculateEffectiveSizes()], and (3) the cumulative
  179. * coefficients of the dump's parent and owned MADs (if present)
  180. * [depth-first pre-order traversal] have already been calculated.
  181. */
  182. static void CalculateDumpCumulativeOwnershipCoefficient(
  183. GlobalDumpGraph::Node* node);
  184. /**
  185. * Calculate the effective size of a memory allocator dump.
  186. *
  187. * In order to simplify the (already complex) calculation, we use the fact
  188. * that effective size is cumulative (unlike regular size), i.e. the
  189. * effective size of a non-leaf node is equal to the sum of effective sizes
  190. * of its children. The effective size of a leaf MAD is calculated as:
  191. *
  192. * effectiveSize(M) = size(M) * cumulativeOwningC(M) * cumulativeOwnedC(M)
  193. *
  194. * This method assumes that (1) the size of the dump and its children [see
  195. * calculateSizes()] and (2) the cumulative owning and owned coefficients
  196. * of the dump (if it's a leaf node) [see the third step of
  197. * calculateEffectiveSizes()] or the effective sizes of its children (if
  198. * it's a non-leaf node) [depth-first post-order traversal] have already
  199. * been calculated.
  200. */
  201. static void CalculateDumpEffectiveSize(GlobalDumpGraph::Node* node);
  202. };
  203. } // namespace memory_instrumentation
  204. #endif