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

Side by Side Diff: systrace/atrace_helper/jni/atrace_process_dump.cc

Issue 2946033002: Android systrace: Optimize memory dumps. (Closed)
Patch Set: for review 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();
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();) {
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 int n_mmaps = mem->mmaps_count();
Primiano Tucci (use gerrit) 2017/06/22 07:55:51 size_t, here and below
kraynov 2017/06/22 09:19:44 Done.
73 for (int 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());
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 mgr->SetGraphicsDumpPredicate([this](const ProcessInfo* process) -> bool {
156 if (!graphics_stats_)
157 return false;
158 return process->is_app;
159 });
160
161 SetupTimer();
162 fprintf(out_, "{\"start_ts\": \"%llu\", \"snapshots\":[\n", GetTimestamp());
163 for (int dump_number = 0; dump_number < dump_count_; dump_number++) {
164 if (dump_number > 0) {
165 fprintf(out_, ",\n");
166 if (!WaitForTimer())
167 break; // Interrupted by signal.
168 }
169 mgr->TakeSnapshot();
170
171 // Smaps are too heavy to serialize. Using only in whitelist mode.
172 if (print_smaps_ && !full_dump_whitelist_.empty()) {
173 smaps_pids.clear();
174 auto processes = mgr->all_processes();
175 for (auto pit = processes->begin(); pit != processes->end(); ++pit) {
176 if (full_dump_whitelist_.count(pit->second->name))
177 smaps_pids.insert(pit->second->pid);
178 }
179 }
180 SerializeSnapshot(mgr->last_snapshot(), smaps_pids);
181 fflush(out_);
182 }
183 fprintf(out_, "],\n");
184 SerializeProcessInfo(mgr->all_processes());
185 CloseTimer();
186
187 fprintf(out_, "}\n");
188 fclose(out_);
189 }
190
191 void AtraceProcessDump::SetupTimer() {
192 timer_fd_ = timerfd_create(CLOCK_MONOTONIC, 0);
193 CHECK(timer_fd_ >= 0);
194 int sec = dump_interval_ms_ / 1000;
195 int nsec = (dump_interval_ms_ % 1000) * 1000000;
196 struct itimerspec ts = {};
197 ts.it_value.tv_nsec = nsec;
198 ts.it_value.tv_sec = sec;
199 ts.it_interval.tv_nsec = nsec;
200 ts.it_interval.tv_sec = sec;
201 CHECK(timerfd_settime(timer_fd_, 0, &ts, nullptr) == 0);
202 }
203
204 bool AtraceProcessDump::WaitForTimer() {
205 uint64_t stub = 0;
206 int res = read(timer_fd_, &stub, sizeof(stub));
207 if (res < 0 && errno == EBADF)
208 return false; // Received SIGINT/SIGTERM signal.
209 CHECK(res > 0);
210 return true;
211 }
212
213 void AtraceProcessDump::CloseTimer() {
214 if (timer_fd_ < 0)
215 return;
216 close(timer_fd_);
217 timer_fd_ = 0;
218 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698