blob: 638435ea4dec69511cba76da586dafa3cbbff15b [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "garnet/bin/memory_monitor/printer.h"
namespace memory {
void Printer::PrintCapture(
const Capture& capture, CaptureLevel level, Sorted sorted) {
auto const& kmem = capture.kmem();
os_ << "K,"
<< capture.time() << ","
<< kmem.total_bytes << ","
<< kmem.free_bytes << ","
<< kmem.wired_bytes << ","
<< kmem.total_heap_bytes << ","
<< kmem.free_heap_bytes << ","
<< kmem.vmo_bytes << ","
<< kmem.mmu_overhead_bytes << ","
<< kmem.ipc_bytes << ","
<< kmem.other_bytes << "\n";
if (level == KMEM) {
return;
}
auto const& koid_to_process = capture.koid_to_process();
std::vector<zx_koid_t> process_koids;
for (auto const& pair : koid_to_process) {
process_koids.push_back(pair.first);
}
if (sorted == SORTED) {
sort(process_koids.begin(), process_koids.end(),
[&koid_to_process](zx_koid_t a, zx_koid_t b) {
auto const& sa = koid_to_process.at(a).stats;
auto const& sb = koid_to_process.at(b).stats;
return sa.mem_private_bytes == sb.mem_private_bytes
? sa.mem_scaled_shared_bytes > sb.mem_scaled_shared_bytes
: sa.mem_private_bytes > sb.mem_private_bytes;
});
}
for (auto const& koid : process_koids) {
auto const& p = koid_to_process.at(koid);
os_ << "P,"
<< p.koid << ","
<< p.name << ","
<< p.stats.mem_mapped_bytes << ","
<< p.stats.mem_private_bytes << ","
<< p.stats.mem_shared_bytes << ","
<< p.stats.mem_scaled_shared_bytes;
for (auto const& v: p.vmos) {
os_ << "," << v;
}
os_ << "\n";
}
if (level == PROCESS) {
return;
}
auto const& koid_to_vmo = capture.koid_to_vmo();
std::vector<zx_koid_t> vmo_koids;
for (auto const& pair : koid_to_vmo) {
vmo_koids.push_back(pair.first);
}
if (sorted == SORTED) {
sort(vmo_koids.begin(), vmo_koids.end(),
[&koid_to_vmo](zx_koid_t a, zx_koid_t b) {
auto const& sa = koid_to_vmo.at(a);
auto const& sb = koid_to_vmo.at(b);
return sa.committed_bytes > sb.committed_bytes;
});
}
for (auto const& koid : vmo_koids) {
auto const& v = koid_to_vmo.at(koid);
os_ << "V,"
<< v.koid << ","
<< v.name << ","
<< v.size_bytes << ","
<< v.parent_koid << ","
<< v.committed_bytes << "\n";
}
os_ << std::flush;
}
void Printer::PrintSummary(
const Summary& summary, CaptureLevel level, Sorted sorted) {
auto& kstats = summary.kstats();
os_ << "Time: " << summary.time()
<< " VMO: " << kstats.vmo_bytes
<< " Free: " << kstats.free_bytes
<< " Wired: " << kstats.wired_bytes
<< " Heap: " << kstats.total_heap_bytes
<< " Heap Free: " << kstats.free_heap_bytes
<< " Overhead: " << kstats.mmu_overhead_bytes
<< " Other: " << kstats.other_bytes << "\n";
if (level == KMEM) {
return;
}
auto const& summaries = summary.process_summaries();
std::vector<ProcessSummary> sorted_summaries;
if (sorted == SORTED) {
sorted_summaries = summaries;
sort(sorted_summaries.begin(), sorted_summaries.end(),
[](ProcessSummary a, ProcessSummary b) {
return a.sizes().private_bytes > b.sizes().private_bytes;
});
}
for (auto const& s : sorted == SORTED ? sorted_summaries : summaries) {
os_ << s.name() << "<" << s.koid() << "> "
<< s.sizes().private_bytes << " "
<< s.sizes().scaled_bytes << " "
<< s.sizes().total_bytes << "\n";
if (level == PROCESS) {
continue;
}
auto const& name_to_sizes = s.name_to_sizes();
std::vector<std::string> names;
for (auto const& pair : name_to_sizes) {
names.push_back(pair.first);
}
if (sorted == SORTED) {
sort(names.begin(), names.end(),
[&name_to_sizes](std::string a, std::string b) {
auto const& sa = name_to_sizes.at(a);
auto const& sb = name_to_sizes.at(b);
return sa.private_bytes == sb.private_bytes
? sa.scaled_bytes > sb.scaled_bytes
: sa.private_bytes > sb.private_bytes;
});
}
for (auto const& name : names) {
auto const& sizes = name_to_sizes.at(name);
if (sizes.total_bytes == 0) {
continue;
}
os_ << " " << name
<< " " << sizes.private_bytes
<< " " << sizes.scaled_bytes
<< " " << sizes.total_bytes << "\n";
}
}
os_ << std::flush;
}
void Printer::OutputSummary(
const Summary& summary, Sorted sorted, zx_koid_t pid) {
auto const& summaries = summary.process_summaries();
std::vector<ProcessSummary> sorted_summaries;
if (sorted == SORTED) {
sorted_summaries = summaries;
sort(sorted_summaries.begin(), sorted_summaries.end(),
[](ProcessSummary a, ProcessSummary b) {
return a.sizes().private_bytes > b.sizes().private_bytes;
});
}
for (auto const& s : sorted == SORTED ? sorted_summaries : summaries) {
if (pid != ZX_KOID_INVALID) {
if (s.koid() != pid) {
continue;
}
auto const& name_to_sizes = s.name_to_sizes();
std::vector<std::string> names;
for (auto const& pair : name_to_sizes) {
names.push_back(pair.first);
}
if (sorted == SORTED) {
sort(names.begin(), names.end(),
[&name_to_sizes](std::string a, std::string b) {
auto const& sa = name_to_sizes.at(a);
auto const& sb = name_to_sizes.at(b);
return sa.private_bytes == sb.private_bytes
? sa.scaled_bytes > sb.scaled_bytes
: sa.private_bytes > sb.private_bytes;
});
}
for (auto const& name : names) {
auto const& sizes = name_to_sizes.at(name);
if (sizes.total_bytes == 0) {
continue;
}
os_ << summary.time() / 1000000000 << ","
<< s.koid() << ","
<< name << ","
<< sizes.private_bytes << ","
<< sizes.scaled_bytes << ","
<< sizes.total_bytes << "\n";
}
continue;
}
auto sizes = s.sizes();
os_ << summary.time() / 1000000000 << ","
<< s.koid() << ","
<< s.name() << ","
<< sizes.private_bytes << ","
<< sizes.scaled_bytes << ","
<< sizes.total_bytes << "\n";
}
os_ << std::flush;
}
} // namespace memory