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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "atrace_process_dump.h"
6
7 #include <sys/time.h>
8 #include <sys/timerfd.h>
9 #include <stdint.h>
10
11 #include <memory>
12 #include <sstream>
13
14 #include "logging.h"
15
16 void AtraceProcessDump::SetFullDumpConfig(const std::string& config) {
17 self_pid_ = (int) getpid();
Primiano Tucci (use gerrit) 2017/06/26 10:07:19 static_cast<int>(getpid()). c-style cast are not a
18 if (config == "all") {
19 full_dump_all_ = true;
20 } else if (config == "apps") {
21 full_dump_apps_ = true;
22 } else {
23 full_dump_whitelist_.clear();
24 std::istringstream ss(config);
25 std::string entry;
26 while (std::getline(ss, entry, ',')) {
27 full_dump_whitelist_.insert(entry);
28 }
29 }
30 }
31
32 void AtraceProcessDump::SerializeSnapshot(
33 const InstantProcessInfo* snapshot, const std::set<int>& smaps_pids) {
34
35 fprintf(out_, "{\"ts\":\"%llu\",\"memdump\":{\n", snapshot->timestamp());
36 const InstantProcessInfo::ProcessSnapshotMap* processes =
37 snapshot->processes();
38 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
39 const InstantProcessInfo::ProcessSnapshot* process = pit->second.get();
40 const ProcessMemoryStats* mem = &process->memory;
41 fprintf(out_, "\"%d\":{", process->pid);
42
43 fprintf(out_, "\"vm\":%llu,\"rss\":%llu",
44 mem->virt_kb(), mem->rss_kb());
45
46 fprintf(out_, ",\"oom_sc\":%d,\"oom_sc_adj\":%d"
47 ",\"min_flt\":%lu,\"maj_flt\":%lu"
48 ",\"utime\":%lu,\"stime\":%lu",
49 process->oom_score, process->oom_score_adj,
50 process->minor_faults, process->major_faults,
51 process->utime, process->stime);
52
53 if (mem->full_stats_available()) {
54 fprintf(out_, ",\"pss\":%llu,\"swp\":%llu"
55 ",\"pc\":%llu,\"pd\":%llu,\"sc\":%llu,\"sd\":%llu",
56 mem->pss_kb(), mem->swapped_kb(),
57 mem->private_clean_kb(), mem->private_dirty_kb(),
58 mem->shared_clean_kb(), mem->shared_dirty_kb());
59 }
60
61 if (mem->gpu_stats_available()) {
62 fprintf(out_, ",\"gpu_egl\":%llu,\"gpu_egl_pss\":%llu"
63 ",\"gpu_gl\":%llu,\"gpu_gl_pss\":%llu"
64 ",\"gpu_etc\":%llu,\"gpu_etc_pss\":%llu",
65 mem->gpu_graphics_kb(), mem->gpu_graphics_pss_kb(),
66 mem->gpu_gl_kb(), mem->gpu_gl_pss_kb(),
67 mem->gpu_other_kb(), mem->gpu_other_pss_kb());
68 }
69
70 if (mem->full_stats_available() && smaps_pids.count(process->pid)) {
71 fprintf(out_, ", \"mmaps\":[");
72 size_t n_mmaps = mem->mmaps_count();
73 for (size_t k = 0; k < n_mmaps; ++k) {
74 const ProcessMemoryStats::MmapInfo* mm = mem->mmap(k);
75 fprintf(out_,
76 "{\"vm\":\"%llx-%llx\",\"file\":\"%s\",\"flags\":\"%s\","
77 "\"pss\":%llu,\"rss\":%llu,\"swp\":%llu,"
78 "\"pc\":%llu,\"pd\":%llu,"
79 "\"sc\":%llu,\"sd\":%llu}",
80 mm->start_addr, mm->end_addr, mm->mapped_file, mm->prot_flags,
81 mm->pss_kb, mm->rss_kb, mm->swapped_kb,
82 mm->private_clean_kb, mm->private_dirty_kb,
83 mm->shared_clean_kb, mm->shared_dirty_kb);
84 if (k < n_mmaps - 1)
85 fprintf(out_, ", ");
86 }
87 fprintf(out_, "]");
88 }
89
90 // TODO(kraynov): Return OOM numbers.
91
92 ++pit;
93 if (pit != processes->end()) {
94 fprintf(out_, "},\n");
95 } else {
96 fprintf(out_, "}}\n");
97 }
98 }
99 fprintf(out_, "}");
100 }
101
102 void AtraceProcessDump::SerializeProcessInfo(
103 const PersistentProcessInfo::ProcessMap* processes) {
104
105 fprintf(out_, "\"processes\":{");
106 for (auto pit = processes->begin(); pit != processes->end();) {
107 const PersistentProcessInfo::ProcessInfo* process = pit->second.get();
108 fprintf(out_, "\"%d\":{", process->pid);
109 fprintf(out_, "\"name\":\"%s\"", process->name.c_str());
110
111 if (!process->in_kernel) {
112 fprintf(out_, ",\"exe\":\"%s\",", process->exe.c_str());
113 fprintf(out_, "\"threads\":{\n");
114 const PersistentProcessInfo::ThreadMap* threads = &process->threads;
115 for (auto tit = threads->begin(); tit != threads->end();) {
116 const PersistentProcessInfo::ThreadInfo* thread = tit->second.get();
117 fprintf(out_, "\"%d\":{", thread->tid);
118 fprintf(out_, "\"name\":\"%s\"", thread->name.c_str());
119
120 ++tit;
121 if (tit != threads->end()) {
122 fprintf(out_, "},\n");
123 } else {
124 fprintf(out_, "}\n");
125 }
126 }
127 fprintf(out_, "}");
128 }
129
130 ++pit;
131 if (pit != processes->end()) {
132 fprintf(out_, "},\n");
133 } else {
134 fprintf(out_, "}\n");
135 }
136 }
137 fprintf(out_, "}");
138 }
139
140 void AtraceProcessDump::RunAndPrintJson(FILE* stream) {
141 using ProcessInfo = PersistentProcessInfo::ProcessInfo;
142 out_ = stream;
143
144 std::set<int> smaps_pids;
145 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
146 mgr->SetFullDumpPredicate([this](const ProcessInfo* process) -> bool {
147 if (full_dump_all_)
148 return !process->in_kernel && (process->pid != self_pid_);
149 if (full_dump_apps_)
150 return process->is_app;
151 if (full_dump_whitelist_.empty())
152 return false;
153 return full_dump_whitelist_.count(process->name) > 0;
154 });
155 if (graphics_stats_)
156 mgr->EnableGraphicsStats();
157
158 SetupTimer();
159 fprintf(out_, "{\"start_ts\": \"%llu\", \"snapshots\":[\n", GetTimestamp());
160 for (int dump_number = 0; dump_number < dump_count_; dump_number++) {
161 if (dump_number > 0) {
162 fprintf(out_, ",\n");
163 if (!WaitForTimer())
164 break; // Interrupted by signal.
165 }
166 mgr->TakeSnapshot();
167
168 // Smaps are too heavy to serialize. Using only in whitelist mode.
169 if (print_smaps_ && !full_dump_whitelist_.empty()) {
170 smaps_pids.clear();
171 auto processes = mgr->all_processes();
172 for (auto pit = processes->begin(); pit != processes->end(); ++pit) {
173 if (full_dump_whitelist_.count(pit->second->name))
174 smaps_pids.insert(pit->second->pid);
175 }
176 }
177 SerializeSnapshot(mgr->last_snapshot(), smaps_pids);
178 fflush(out_);
179 }
180 fprintf(out_, "],\n");
181 SerializeProcessInfo(mgr->all_processes());
182 CloseTimer();
183
184 fprintf(out_, "}\n");
185 fclose(out_);
186 }
187
188 void AtraceProcessDump::SetupTimer() {
189 timer_fd_ = timerfd_create(CLOCK_MONOTONIC, 0);
190 CHECK(timer_fd_ >= 0);
191 int sec = dump_interval_ms_ / 1000;
192 int nsec = (dump_interval_ms_ % 1000) * 1000000;
193 struct itimerspec ts = {};
194 ts.it_value.tv_nsec = nsec;
195 ts.it_value.tv_sec = sec;
196 ts.it_interval.tv_nsec = nsec;
197 ts.it_interval.tv_sec = sec;
198 CHECK(timerfd_settime(timer_fd_, 0, &ts, nullptr) == 0);
199 }
200
201 bool AtraceProcessDump::WaitForTimer() {
202 uint64_t stub = 0;
203 int res = read(timer_fd_, &stub, sizeof(stub));
204 if (res < 0 && errno == EBADF)
205 return false; // Received SIGINT/SIGTERM signal.
206 CHECK(res > 0);
207 return true;
208 }
209
210 void AtraceProcessDump::CloseTimer() {
211 if (timer_fd_ < 0)
212 return;
213 close(timer_fd_);
214 timer_fd_ = 0;
215 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698