global_dump_graph_converter.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2020 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. #include "services/resource_coordinator/memory_instrumentation/global_dump_graph_converter.h"
  5. #include <list>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/trace_event/process_memory_dump.h"
  11. #include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
  12. namespace memory_instrumentation {
  13. using perfetto::trace_processor::GlobalNodeGraph;
  14. GlobalDumpGraphConverter::GlobalDumpGraphConverter() = default;
  15. GlobalDumpGraphConverter::~GlobalDumpGraphConverter() = default;
  16. std::unique_ptr<GlobalDumpGraph> GlobalDumpGraphConverter::Convert(
  17. const GlobalNodeGraph& input) const {
  18. NodePointerPerfettoToChromeMap pointer_map;
  19. auto output = std::make_unique<GlobalDumpGraph>();
  20. CopyAndConvertProcessDumps(input, output.get(), &pointer_map);
  21. CopyAndConvertSharedMemoryGraph(input, output.get(), &pointer_map);
  22. CopyAndConvertEdges(input, output.get(), &pointer_map);
  23. return output;
  24. }
  25. void GlobalDumpGraphConverter::CopyAndConvertProcessDumps(
  26. const GlobalNodeGraph& input,
  27. GlobalDumpGraph* output,
  28. NodePointerPerfettoToChromeMap* pointer_map) const {
  29. for (const auto& input_entry : input.process_node_graphs()) {
  30. const base::ProcessId process_id = input_entry.first;
  31. const GlobalNodeGraph::Process* input_process = input_entry.second.get();
  32. if (input_process == nullptr)
  33. continue;
  34. GlobalDumpGraph::Process* output_process =
  35. output->CreateGraphForProcess(process_id);
  36. CopyAndConvertNodeTree(input_process->root(), output_process, {},
  37. pointer_map);
  38. }
  39. }
  40. void GlobalDumpGraphConverter::CopyAndConvertSharedMemoryGraph(
  41. const GlobalNodeGraph& input,
  42. GlobalDumpGraph* output,
  43. NodePointerPerfettoToChromeMap* pointer_map) const {
  44. CopyAndConvertNodeTree(input.shared_memory_graph()->root(),
  45. output->shared_memory_graph(), {}, pointer_map);
  46. }
  47. void GlobalDumpGraphConverter::CopyAndConvertNodeTree(
  48. const GlobalNodeGraph::Node* input,
  49. GlobalDumpGraph::Process* output,
  50. const std::string& node_path,
  51. NodePointerPerfettoToChromeMap* pointer_map) const {
  52. DCHECK(input);
  53. for (const auto& entry : input->const_children()) {
  54. const std::string path = node_path + "/" + entry.first;
  55. const GlobalNodeGraph::Node* raw_child = entry.second;
  56. GlobalDumpGraph::Node* child =
  57. output->CreateNode(ConvertMemoryAllocatorDumpGuid(raw_child->id()),
  58. path, raw_child->is_weak());
  59. CopyNodeMembers(*raw_child, child);
  60. CopyAndConvertNodeTree(raw_child, output, path, pointer_map);
  61. pointer_map->emplace(raw_child, child);
  62. }
  63. }
  64. base::trace_event::MemoryAllocatorDumpGuid
  65. GlobalDumpGraphConverter::ConvertMemoryAllocatorDumpGuid(
  66. const perfetto::trace_processor::MemoryAllocatorNodeId& input) const {
  67. return base::trace_event::MemoryAllocatorDumpGuid(input.ToUint64());
  68. }
  69. void GlobalDumpGraphConverter::CopyNodeMembers(
  70. const GlobalNodeGraph::Node& input,
  71. GlobalDumpGraph::Node* output) const {
  72. for (const auto& item : input.const_entries()) {
  73. const std::string& name = item.first;
  74. const GlobalNodeGraph::Node::Entry& entry = item.second;
  75. if (entry.type == GlobalNodeGraph::Node::Entry::kUInt64) {
  76. output->AddEntry(name, ConvertScalarUnits(entry.units),
  77. entry.value_uint64);
  78. } else {
  79. output->AddEntry(name, entry.value_string);
  80. }
  81. }
  82. output->set_weak(input.is_weak());
  83. output->set_explicit(input.is_explicit());
  84. output->add_not_owned_sub_size(input.not_owned_sub_size());
  85. output->add_not_owning_sub_size(input.not_owning_sub_size());
  86. output->set_owned_coefficient(input.owned_coefficient());
  87. output->set_owning_coefficient(input.owning_coefficient());
  88. output->set_cumulative_owned_coefficient(
  89. input.cumulative_owned_coefficient());
  90. output->set_cumulative_owning_coefficient(
  91. input.cumulative_owning_coefficient());
  92. }
  93. void GlobalDumpGraphConverter::CopyAndConvertEdges(
  94. const GlobalNodeGraph& input,
  95. GlobalDumpGraph* output,
  96. NodePointerPerfettoToChromeMap* pointer_map) const {
  97. for (const auto& input_edge : input.edges()) {
  98. CopyAndConvertEdge(input_edge, output, pointer_map);
  99. }
  100. }
  101. void GlobalDumpGraphConverter::CopyAndConvertEdge(
  102. const GlobalNodeGraph::Edge& input,
  103. GlobalDumpGraph* output,
  104. const NodePointerPerfettoToChromeMap* pointer_map) const {
  105. DCHECK(input.source());
  106. DCHECK(input.target());
  107. GlobalDumpGraph::Node* source = pointer_map->at(input.source());
  108. GlobalDumpGraph::Node* target = pointer_map->at(input.target());
  109. DCHECK(source);
  110. DCHECK(target);
  111. output->AddNodeOwnershipEdge(source, target, input.priority());
  112. }
  113. GlobalDumpGraph::Node::Entry::ScalarUnits
  114. GlobalDumpGraphConverter::ConvertScalarUnits(
  115. GlobalNodeGraph::Node::Entry::ScalarUnits input) const {
  116. using PerfettoScalarUnits = GlobalNodeGraph::Node::Entry::ScalarUnits;
  117. using ChromeScalarUnits = GlobalDumpGraph::Node::Entry::ScalarUnits;
  118. switch (input) {
  119. case PerfettoScalarUnits::kObjects:
  120. return ChromeScalarUnits::kObjects;
  121. case PerfettoScalarUnits::kBytes:
  122. return ChromeScalarUnits::kBytes;
  123. }
  124. NOTREACHED();
  125. }
  126. } // namespace memory_instrumentation