Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(384)

Unified Diff: systrace/atrace_helper/jni/atrace_process_dump.cc

Issue 2946033002: Android systrace: Optimize memory dumps. (Closed)
Patch Set: fix Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: systrace/atrace_helper/jni/atrace_process_dump.cc
diff --git a/systrace/atrace_helper/jni/atrace_process_dump.cc b/systrace/atrace_helper/jni/atrace_process_dump.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0a6b9f449155c836dd14754b6708f3cceab03f0f
--- /dev/null
+++ b/systrace/atrace_helper/jni/atrace_process_dump.cc
@@ -0,0 +1,215 @@
+// Copyright 2017 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 "atrace_process_dump.h"
+
+#include <sys/time.h>
+#include <sys/timerfd.h>
+#include <stdint.h>
+
+#include <memory>
+#include <sstream>
+
+#include "logging.h"
+
+void AtraceProcessDump::SetFullDumpConfig(const std::string& config) {
+ self_pid_ = (int) getpid();
Primiano Tucci (use gerrit) 2017/06/26 10:07:19 static_cast<int>(getpid()). c-style cast are not a
+ if (config == "all") {
+ full_dump_all_ = true;
+ } else if (config == "apps") {
+ full_dump_apps_ = true;
+ } else {
+ full_dump_whitelist_.clear();
+ std::istringstream ss(config);
+ std::string entry;
+ while (std::getline(ss, entry, ',')) {
+ full_dump_whitelist_.insert(entry);
+ }
+ }
+}
+
+void AtraceProcessDump::SerializeSnapshot(
+ const InstantProcessInfo* snapshot, const std::set<int>& smaps_pids) {
+
+ fprintf(out_, "{\"ts\":\"%llu\",\"memdump\":{\n", snapshot->timestamp());
+ const InstantProcessInfo::ProcessSnapshotMap* processes =
+ snapshot->processes();
+ for (auto pit = processes->begin(); pit != processes->end();) {
Primiano Tucci (use gerrit) 2017/06/26 10:07:20 I thought this was a typo (pit -> pid) but then re
+ const InstantProcessInfo::ProcessSnapshot* process = pit->second.get();
+ const ProcessMemoryStats* mem = &process->memory;
+ fprintf(out_, "\"%d\":{", process->pid);
+
+ fprintf(out_, "\"vm\":%llu,\"rss\":%llu",
+ mem->virt_kb(), mem->rss_kb());
+
+ fprintf(out_, ",\"oom_sc\":%d,\"oom_sc_adj\":%d"
+ ",\"min_flt\":%lu,\"maj_flt\":%lu"
+ ",\"utime\":%lu,\"stime\":%lu",
+ process->oom_score, process->oom_score_adj,
+ process->minor_faults, process->major_faults,
+ process->utime, process->stime);
+
+ if (mem->full_stats_available()) {
+ fprintf(out_, ",\"pss\":%llu,\"swp\":%llu"
+ ",\"pc\":%llu,\"pd\":%llu,\"sc\":%llu,\"sd\":%llu",
+ mem->pss_kb(), mem->swapped_kb(),
+ mem->private_clean_kb(), mem->private_dirty_kb(),
+ mem->shared_clean_kb(), mem->shared_dirty_kb());
+ }
+
+ if (mem->gpu_stats_available()) {
+ fprintf(out_, ",\"gpu_egl\":%llu,\"gpu_egl_pss\":%llu"
+ ",\"gpu_gl\":%llu,\"gpu_gl_pss\":%llu"
+ ",\"gpu_etc\":%llu,\"gpu_etc_pss\":%llu",
+ mem->gpu_graphics_kb(), mem->gpu_graphics_pss_kb(),
+ mem->gpu_gl_kb(), mem->gpu_gl_pss_kb(),
+ mem->gpu_other_kb(), mem->gpu_other_pss_kb());
+ }
+
+ if (mem->full_stats_available() && smaps_pids.count(process->pid)) {
+ fprintf(out_, ", \"mmaps\":[");
+ size_t n_mmaps = mem->mmaps_count();
+ for (size_t k = 0; k < n_mmaps; ++k) {
+ const ProcessMemoryStats::MmapInfo* mm = mem->mmap(k);
+ fprintf(out_,
+ "{\"vm\":\"%llx-%llx\",\"file\":\"%s\",\"flags\":\"%s\","
+ "\"pss\":%llu,\"rss\":%llu,\"swp\":%llu,"
+ "\"pc\":%llu,\"pd\":%llu,"
+ "\"sc\":%llu,\"sd\":%llu}",
+ mm->start_addr, mm->end_addr, mm->mapped_file, mm->prot_flags,
+ mm->pss_kb, mm->rss_kb, mm->swapped_kb,
+ mm->private_clean_kb, mm->private_dirty_kb,
+ mm->shared_clean_kb, mm->shared_dirty_kb);
+ if (k < n_mmaps - 1)
+ fprintf(out_, ", ");
+ }
+ fprintf(out_, "]");
+ }
+
+ // TODO(kraynov): Return OOM numbers.
+
+ ++pit;
+ if (pit != processes->end()) {
+ fprintf(out_, "},\n");
+ } else {
+ fprintf(out_, "}}\n");
+ }
+ }
+ fprintf(out_, "}");
+}
+
+void AtraceProcessDump::SerializeProcessInfo(
+ const PersistentProcessInfo::ProcessMap* processes) {
+
+ fprintf(out_, "\"processes\":{");
+ for (auto pit = processes->begin(); pit != processes->end();) {
+ const PersistentProcessInfo::ProcessInfo* process = pit->second.get();
+ fprintf(out_, "\"%d\":{", process->pid);
+ fprintf(out_, "\"name\":\"%s\"", process->name.c_str());
+
+ if (!process->in_kernel) {
+ fprintf(out_, ",\"exe\":\"%s\",", process->exe.c_str());
+ fprintf(out_, "\"threads\":{\n");
+ const PersistentProcessInfo::ThreadMap* threads = &process->threads;
+ for (auto tit = threads->begin(); tit != threads->end();) {
+ const PersistentProcessInfo::ThreadInfo* thread = tit->second.get();
+ fprintf(out_, "\"%d\":{", thread->tid);
+ fprintf(out_, "\"name\":\"%s\"", thread->name.c_str());
+
+ ++tit;
+ if (tit != threads->end()) {
+ fprintf(out_, "},\n");
+ } else {
+ fprintf(out_, "}\n");
+ }
+ }
+ fprintf(out_, "}");
+ }
+
+ ++pit;
+ if (pit != processes->end()) {
+ fprintf(out_, "},\n");
+ } else {
+ fprintf(out_, "}\n");
+ }
+ }
+ fprintf(out_, "}");
+}
+
+void AtraceProcessDump::RunAndPrintJson(FILE* stream) {
+ using ProcessInfo = PersistentProcessInfo::ProcessInfo;
+ out_ = stream;
+
+ std::set<int> smaps_pids;
+ std::unique_ptr<ProcessDumpManager> mgr(new ProcessDumpManager());
Primiano Tucci (use gerrit) 2017/06/26 10:07:19 Copy/pasting to what I said in the previous review
+ mgr->SetFullDumpPredicate([this](const ProcessInfo* process) -> bool {
+ if (full_dump_all_)
+ return !process->in_kernel && (process->pid != self_pid_);
+ if (full_dump_apps_)
+ return process->is_app;
+ if (full_dump_whitelist_.empty())
+ return false;
+ return full_dump_whitelist_.count(process->name) > 0;
+ });
+ if (graphics_stats_)
+ mgr->EnableGraphicsStats();
+
+ SetupTimer();
+ fprintf(out_, "{\"start_ts\": \"%llu\", \"snapshots\":[\n", GetTimestamp());
+ for (int dump_number = 0; dump_number < dump_count_; dump_number++) {
+ if (dump_number > 0) {
+ fprintf(out_, ",\n");
+ if (!WaitForTimer())
+ break; // Interrupted by signal.
+ }
+ mgr->TakeSnapshot();
+
+ // Smaps are too heavy to serialize. Using only in whitelist mode.
+ if (print_smaps_ && !full_dump_whitelist_.empty()) {
+ smaps_pids.clear();
+ auto processes = mgr->all_processes();
+ for (auto pit = processes->begin(); pit != processes->end(); ++pit) {
+ if (full_dump_whitelist_.count(pit->second->name))
+ smaps_pids.insert(pit->second->pid);
+ }
+ }
+ SerializeSnapshot(mgr->last_snapshot(), smaps_pids);
+ fflush(out_);
+ }
+ fprintf(out_, "],\n");
+ SerializeProcessInfo(mgr->all_processes());
+ CloseTimer();
+
+ fprintf(out_, "}\n");
+ fclose(out_);
+}
+
+void AtraceProcessDump::SetupTimer() {
+ timer_fd_ = timerfd_create(CLOCK_MONOTONIC, 0);
+ CHECK(timer_fd_ >= 0);
+ int sec = dump_interval_ms_ / 1000;
+ int nsec = (dump_interval_ms_ % 1000) * 1000000;
+ struct itimerspec ts = {};
+ ts.it_value.tv_nsec = nsec;
+ ts.it_value.tv_sec = sec;
+ ts.it_interval.tv_nsec = nsec;
+ ts.it_interval.tv_sec = sec;
+ CHECK(timerfd_settime(timer_fd_, 0, &ts, nullptr) == 0);
+}
+
+bool AtraceProcessDump::WaitForTimer() {
+ uint64_t stub = 0;
+ int res = read(timer_fd_, &stub, sizeof(stub));
+ if (res < 0 && errno == EBADF)
+ return false; // Received SIGINT/SIGTERM signal.
+ CHECK(res > 0);
+ return true;
+}
+
+void AtraceProcessDump::CloseTimer() {
+ if (timer_fd_ < 0)
+ return;
+ close(timer_fd_);
+ timer_fd_ = 0;
+}

Powered by Google App Engine
This is Rietveld 408576698