blob: e6c09f7a4763636b95543c1a4722dae0fe03c9b6 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h"
#include <list>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/trace_event/process_memory_dump.h"
#include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
namespace memory_instrumentation {
MemoryDumpMapConverter::MemoryDumpMapConverter() = default;
MemoryDumpMapConverter::~MemoryDumpMapConverter() = default;
perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap
MemoryDumpMapConverter::Convert(const MemoryDumpMap& input) {
perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap output;
for (const auto& entry : input) {
const base::ProcessId process_id = entry.first;
const base::trace_event::ProcessMemoryDump* process_dump = entry.second;
if (process_dump == nullptr)
continue;
output.emplace(process_id, ConvertProcessMemoryDump(*process_dump));
}
return output;
}
std::unique_ptr<MemoryDumpMapConverter::PerfettoProcessMemoryNode>
MemoryDumpMapConverter::ConvertProcessMemoryDump(
const base::trace_event::ProcessMemoryDump& input) {
const perfetto::trace_processor::LevelOfDetail level_of_detail =
ConvertLevelOfDetail(input.dump_args().level_of_detail);
MemoryDumpMapConverter::PerfettoProcessMemoryNode::MemoryNodesMap nodes_map =
ConvertAllocatorDumps(input);
MemoryDumpMapConverter::PerfettoProcessMemoryNode::AllocatorNodeEdgesMap
edges_map = ConvertAllocatorDumpEdges(input);
return std::make_unique<PerfettoProcessMemoryNode>(
level_of_detail, std::move(edges_map), std::move(nodes_map));
}
perfetto::trace_processor::LevelOfDetail
MemoryDumpMapConverter::ConvertLevelOfDetail(
const base::trace_event::MemoryDumpLevelOfDetail& input) const {
switch (input) {
case base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND:
return perfetto::trace_processor::LevelOfDetail::kBackground;
case base::trace_event::MemoryDumpLevelOfDetail::LIGHT:
return perfetto::trace_processor::LevelOfDetail::kLight;
case base::trace_event::MemoryDumpLevelOfDetail::DETAILED:
return perfetto::trace_processor::LevelOfDetail::kDetailed;
}
return perfetto::trace_processor::LevelOfDetail::kDetailed;
}
std::vector<perfetto::trace_processor::RawMemoryGraphNode::MemoryNodeEntry>
MemoryDumpMapConverter::ConvertAllocatorDumpEntries(
const base::trace_event::MemoryAllocatorDump& input) const {
std::vector<perfetto::trace_processor::RawMemoryGraphNode::MemoryNodeEntry>
output;
for (const auto& entry : input.entries()) {
if (entry.entry_type ==
base::trace_event::MemoryAllocatorDump::Entry::kUint64) {
output.emplace_back(entry.name, entry.units, entry.value_uint64);
} else {
output.emplace_back(entry.name, entry.units, entry.value_string);
}
}
return output;
}
std::unique_ptr<perfetto::trace_processor::RawMemoryGraphNode>
MemoryDumpMapConverter::ConvertMemoryAllocatorDump(
const base::trace_event::MemoryAllocatorDump& input) const {
auto output = std::make_unique<perfetto::trace_processor::RawMemoryGraphNode>(
input.absolute_name(), ConvertLevelOfDetail(input.level_of_detail()),
ConvertMemoryAllocatorDumpGuid(input.guid()),
ConvertAllocatorDumpEntries(input));
CopyAndConvertAllocatorDumpFlags(input, output.get());
return output;
}
void MemoryDumpMapConverter::CopyAndConvertAllocatorDumpFlags(
const base::trace_event::MemoryAllocatorDump& input,
perfetto::trace_processor::RawMemoryGraphNode* output) const {
output->clear_flags(output->flags());
output->set_flags(
input.flags() & base::trace_event::MemoryAllocatorDump::WEAK
? perfetto::trace_processor::RawMemoryGraphNode::kWeak
: perfetto::trace_processor::RawMemoryGraphNode::kDefault);
}
MemoryDumpMapConverter::PerfettoProcessMemoryNode::MemoryNodesMap
MemoryDumpMapConverter::ConvertAllocatorDumps(
const base::trace_event::ProcessMemoryDump& input) const {
MemoryDumpMapConverter::PerfettoProcessMemoryNode::MemoryNodesMap output;
for (const auto& entry : input.allocator_dumps()) {
const std::unique_ptr<base::trace_event::MemoryAllocatorDump>& dump =
entry.second;
output.emplace(entry.first, ConvertMemoryAllocatorDump(*dump));
}
return output;
}
MemoryDumpMapConverter::PerfettoProcessMemoryNode::AllocatorNodeEdgesMap
MemoryDumpMapConverter::ConvertAllocatorDumpEdges(
const base::trace_event::ProcessMemoryDump& input) const {
MemoryDumpMapConverter::PerfettoProcessMemoryNode::AllocatorNodeEdgesMap
output;
for (const auto& entry : input.allocator_dumps_edges()) {
std::unique_ptr<perfetto::trace_processor::MemoryGraphEdge> edge =
ConvertAllocatorDumpEdge(entry.second);
const perfetto::trace_processor::MemoryAllocatorNodeId source =
edge->source;
output.emplace(source, std::move(edge));
}
return output;
}
std::unique_ptr<perfetto::trace_processor::MemoryGraphEdge>
MemoryDumpMapConverter::ConvertAllocatorDumpEdge(
const base::trace_event::ProcessMemoryDump::MemoryAllocatorDumpEdge& input)
const {
return std::make_unique<perfetto::trace_processor::MemoryGraphEdge>(
ConvertMemoryAllocatorDumpGuid(input.source),
ConvertMemoryAllocatorDumpGuid(input.target), input.importance,
input.overridable);
}
perfetto::trace_processor::MemoryAllocatorNodeId
MemoryDumpMapConverter::ConvertMemoryAllocatorDumpGuid(
const base::trace_event::MemoryAllocatorDumpGuid& input) const {
return perfetto::trace_processor::MemoryAllocatorNodeId(input.ToUint64());
}
} // namespace memory_instrumentation