blob: f765a332f0450e2abfa78a6dfd4e3bb2d4f5ee70 [file] [log] [blame]
Lalit Maganti93b76362018-06-01 03:03:58 +01001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Primiano Tucci0d72a312018-08-07 14:42:45 +010017#include "src/trace_processor/proto_trace_parser.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010018
Primiano Tucci132a34d2018-09-19 19:34:01 +010019#include <string.h>
20
Lalit Magantidf3e9262018-06-04 17:45:00 +010021#include <string>
22
Primiano Tuccid933d912018-09-04 09:15:07 +010023#include "perfetto/base/logging.h"
Primiano Tucci2da5d2e2018-08-10 14:23:31 +010024#include "perfetto/base/string_view.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010025#include "perfetto/base/utils.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010026#include "perfetto/protozero/proto_decoder.h"
Isabelle Taylor54ce7052018-10-01 14:00:15 +010027#include "perfetto/traced/sys_stats_counters.h"
Isabelle Taylora97c5f52018-10-23 17:36:12 +010028#include "src/trace_processor/event_tracker.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010029#include "src/trace_processor/process_tracker.h"
Hector Dearman947f12a2018-09-11 16:50:36 +010030#include "src/trace_processor/slice_tracker.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010031#include "src/trace_processor/trace_processor_context.h"
32
Lalit Magantidf3e9262018-06-04 17:45:00 +010033#include "perfetto/trace/trace.pb.h"
34#include "perfetto/trace/trace_packet.pb.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010035
36namespace perfetto {
37namespace trace_processor {
38
Hector Dearman947f12a2018-09-11 16:50:36 +010039// We have to handle trace_marker events of a few different types:
40// 1. some random text
41// 2. B|1636|pokeUserActivity
42// 3. E|1636
43// 4. C|1636|wq:monitor|0
44bool ParseSystraceTracePoint(base::StringView str, SystraceTracePoint* out) {
45 // THIS char* IS NOT NULL TERMINATED.
46 const char* s = str.data();
47 size_t len = str.size();
48
Hector Dearman9e6ddd82018-09-21 10:17:02 +010049 // If str matches '[BEC]\|[0-9]+[\|\n]' set tid_length to the length of
Hector Dearman947f12a2018-09-11 16:50:36 +010050 // the number. Otherwise return false.
Lalit Magantide6267f2018-11-08 12:35:34 +000051 if (s[1] != '|' && s[1] != '\n')
Hector Dearman947f12a2018-09-11 16:50:36 +010052 return false;
53 if (s[0] != 'B' && s[0] != 'E' && s[0] != 'C')
54 return false;
Lalit Magantide6267f2018-11-08 12:35:34 +000055 size_t tid_length = 0;
56 for (size_t i = 2; i < len; i++) {
Hector Dearman947f12a2018-09-11 16:50:36 +010057 if (s[i] == '|' || s[i] == '\n') {
Hector Dearman9e6ddd82018-09-21 10:17:02 +010058 tid_length = i - 2;
Hector Dearman947f12a2018-09-11 16:50:36 +010059 break;
60 }
61 if (s[i] < '0' || s[i] > '9')
62 return false;
63 }
64
Lalit Magantide6267f2018-11-08 12:35:34 +000065 if (tid_length == 0) {
66 out->tid = 0;
67 } else {
68 std::string tid_str(s + 2, tid_length);
69 out->tid = static_cast<uint32_t>(std::stoi(tid_str.c_str()));
70 }
Hector Dearman947f12a2018-09-11 16:50:36 +010071
72 out->phase = s[0];
73 switch (s[0]) {
74 case 'B': {
Hector Dearman9e6ddd82018-09-21 10:17:02 +010075 size_t name_index = 2 + tid_length + 1;
Hector Dearman947f12a2018-09-11 16:50:36 +010076 out->name = base::StringView(s + name_index, len - name_index);
77 return true;
78 }
Isabelle Taylor31e04402018-09-19 12:13:25 +010079 case 'E': {
Hector Dearman947f12a2018-09-11 16:50:36 +010080 return true;
Isabelle Taylor31e04402018-09-19 12:13:25 +010081 }
82 case 'C': {
Hector Dearman9e6ddd82018-09-21 10:17:02 +010083 size_t name_index = 2 + tid_length + 1;
Isabelle Taylor31e04402018-09-19 12:13:25 +010084 size_t name_length = 0;
85 for (size_t i = name_index; i < len; i++) {
86 if (s[i] == '|' || s[i] == '\n') {
87 name_length = i - name_index;
88 break;
89 }
90 }
91 out->name = base::StringView(s + name_index, name_length);
92 size_t value_index = name_index + name_length + 1;
93 char value_str[32];
Primiano Tucci132a34d2018-09-19 19:34:01 +010094 strcpy(value_str, s + value_index);
Isabelle Taylor31e04402018-09-19 12:13:25 +010095 out->value = std::stod(value_str);
Hector Dearman947f12a2018-09-11 16:50:36 +010096 return true;
Isabelle Taylor31e04402018-09-19 12:13:25 +010097 }
Hector Dearman947f12a2018-09-11 16:50:36 +010098 default:
99 return false;
100 }
101}
102
Lalit Magantidf3e9262018-06-04 17:45:00 +0100103using protozero::ProtoDecoder;
104using protozero::proto_utils::kFieldTypeLengthDelimited;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100105
Primiano Tucci7e330292018-08-24 19:10:52 +0200106ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
Isabelle Taylor15314ea2018-09-19 11:35:19 +0100107 : context_(context),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100108 cpu_freq_name_id_(context->storage->InternString("cpufreq")),
109 num_forks_name_id_(context->storage->InternString("num_forks")),
110 num_irq_total_name_id_(context->storage->InternString("num_irq_total")),
111 num_softirq_total_name_id_(
112 context->storage->InternString("num_softirq_total")),
113 num_irq_name_id_(context->storage->InternString("num_irq")),
114 num_softirq_name_id_(context->storage->InternString("num_softirq")),
115 cpu_times_user_ns_id_(
116 context->storage->InternString("cpu.times.user_ns")),
117 cpu_times_user_ice_ns_id_(
118 context->storage->InternString("cpu.times.user_ice_ns")),
119 cpu_times_system_mode_ns_id_(
120 context->storage->InternString("cpu.times.system_mode_ns")),
121 cpu_times_idle_ns_id_(
122 context->storage->InternString("cpu.times.idle_ns")),
123 cpu_times_io_wait_ns_id_(
124 context->storage->InternString("cpu.times.io_wait_ns")),
125 cpu_times_irq_ns_id_(context->storage->InternString("cpu.times.irq_ns")),
126 cpu_times_softirq_ns_id_(
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100127 context->storage->InternString("cpu.times.softirq_ns")),
128 ion_heap_grow_id_(context->storage->InternString("ion_heap_grow")),
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000129 ion_heap_shrink_id_(context->storage->InternString("ion_heap_shrink")),
130 signal_deliver_id_(context->storage->InternString("signal_deliver")),
131 signal_generate_id_(context->storage->InternString("signal_generate")) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100132 for (const auto& name : BuildMeminfoCounterNames()) {
133 meminfo_strs_id_.emplace_back(context->storage->InternString(name));
134 }
135 for (const auto& name : BuildVmstatCounterNames()) {
136 vmstat_strs_id_.emplace_back(context->storage->InternString(name));
137 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100138 rss_members_.emplace_back(
139 context->storage->InternString("rss_stat.mm_filepages"));
140 rss_members_.emplace_back(
141 context->storage->InternString("rss_stat.mm_anonpages"));
142 rss_members_.emplace_back(
143 context->storage->InternString("rss_stat.mm_swapents"));
144 rss_members_.emplace_back(
145 context->storage->InternString("rss_stat.nr_mm_counters"));
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700146
147 using MemCounters = protos::ProcessStats::MemCounters;
148 proc_mem_counter_names_[MemCounters::kVmSizeKbFieldNumber] =
149 context->storage->InternString("mem.virt");
150 proc_mem_counter_names_[MemCounters::kVmRssKbFieldNumber] =
151 context->storage->InternString("mem.rss");
152 proc_mem_counter_names_[MemCounters::kRssAnonKbFieldNumber] =
153 context->storage->InternString("mem.rss.anon");
154 proc_mem_counter_names_[MemCounters::kRssFileKbFieldNumber] =
155 context->storage->InternString("mem.rss.file");
156 proc_mem_counter_names_[MemCounters::kRssShmemKbFieldNumber] =
157 context->storage->InternString("mem.rss.shmem");
158 proc_mem_counter_names_[MemCounters::kVmSwapKbFieldNumber] =
159 context->storage->InternString("mem.swap");
160 proc_mem_counter_names_[MemCounters::kVmLockedKbFieldNumber] =
161 context->storage->InternString("mem.locked");
162 proc_mem_counter_names_[MemCounters::kVmHwmKbFieldNumber] =
163 context->storage->InternString("mem.rss.watermark");
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100164}
Lalit Maganti93b76362018-06-01 03:03:58 +0100165
Primiano Tucci0d72a312018-08-07 14:42:45 +0100166ProtoTraceParser::~ProtoTraceParser() = default;
167
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100168void ProtoTraceParser::ParseTracePacket(uint64_t ts, TraceBlobView packet) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100169 ProtoDecoder decoder(packet.data(), packet.length());
Lalit Maganti93b76362018-06-01 03:03:58 +0100170
Lalit Magantidf3e9262018-06-04 17:45:00 +0100171 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
172 switch (fld.id) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100173 case protos::TracePacket::kProcessTreeFieldNumber: {
174 const size_t fld_off = packet.offset_of(fld.data());
175 ParseProcessTree(packet.slice(fld_off, fld.size()));
Isabelle Taylord80932a2018-06-19 17:00:47 +0100176 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100177 }
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700178 case protos::TracePacket::kProcessStatsFieldNumber: {
179 const size_t fld_off = packet.offset_of(fld.data());
180 ParseProcessStats(ts, packet.slice(fld_off, fld.size()));
181 break;
182 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100183 case protos::TracePacket::kSysStatsFieldNumber: {
184 const size_t fld_off = packet.offset_of(fld.data());
185 ParseSysStats(ts, packet.slice(fld_off, fld.size()));
186 break;
187 }
Lalit Magantidf3e9262018-06-04 17:45:00 +0100188 default:
189 break;
190 }
191 }
192 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
193}
194
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100195void ProtoTraceParser::ParseSysStats(uint64_t ts, TraceBlobView stats) {
196 ProtoDecoder decoder(stats.data(), stats.length());
197 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
198 switch (fld.id) {
199 case protos::SysStats::kMeminfoFieldNumber: {
200 const size_t fld_off = stats.offset_of(fld.data());
201 ParseMemInfo(ts, stats.slice(fld_off, fld.size()));
202 break;
203 }
204 case protos::SysStats::kVmstatFieldNumber: {
205 const size_t fld_off = stats.offset_of(fld.data());
206 ParseVmStat(ts, stats.slice(fld_off, fld.size()));
207 break;
208 }
209 case protos::SysStats::kCpuStatFieldNumber: {
210 const size_t fld_off = stats.offset_of(fld.data());
211 ParseCpuTimes(ts, stats.slice(fld_off, fld.size()));
212 break;
213 }
214 case protos::SysStats::kNumIrqFieldNumber: {
215 const size_t fld_off = stats.offset_of(fld.data());
216 ParseIrqCount(ts, stats.slice(fld_off, fld.size()),
217 /*is_softirq=*/false);
218 break;
219 }
220 case protos::SysStats::kNumSoftirqFieldNumber: {
221 const size_t fld_off = stats.offset_of(fld.data());
222 ParseIrqCount(ts, stats.slice(fld_off, fld.size()),
223 /*is_softirq=*/true);
224 break;
225 }
226 case protos::SysStats::kNumForksFieldNumber: {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100227 context_->event_tracker->PushCounter(
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100228 ts, fld.as_uint32(), num_forks_name_id_, 0, RefType::kNoRef);
229 break;
230 }
231 case protos::SysStats::kNumIrqTotalFieldNumber: {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100232 context_->event_tracker->PushCounter(
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100233 ts, fld.as_uint32(), num_irq_total_name_id_, 0, RefType::kNoRef);
234 break;
235 }
236 case protos::SysStats::kNumSoftirqTotalFieldNumber: {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100237 context_->event_tracker->PushCounter(ts, fld.as_uint32(),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100238 num_softirq_total_name_id_, 0,
239 RefType::kNoRef);
240 break;
241 }
242 default:
243 break;
244 }
245 }
246}
247void ProtoTraceParser::ParseIrqCount(uint64_t ts,
248 TraceBlobView irq,
249 bool is_soft) {
250 ProtoDecoder decoder(irq.data(), irq.length());
251 uint32_t key = 0;
252 uint32_t value = 0;
253 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
254 switch (fld.id) {
255 case protos::SysStats::InterruptCount::kIrqFieldNumber:
256 key = fld.as_uint32();
257 break;
258 case protos::SysStats::InterruptCount::kCountFieldNumber:
259 value = fld.as_uint32();
260 break;
261 }
262 }
263 RefType ref_type = is_soft ? RefType::kIrq : RefType::kSoftIrq;
264 StringId name_id = is_soft ? num_irq_name_id_ : num_softirq_name_id_;
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100265 context_->event_tracker->PushCounter(ts, value, name_id, key, ref_type);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100266}
267
268void ProtoTraceParser::ParseMemInfo(uint64_t ts, TraceBlobView mem) {
269 ProtoDecoder decoder(mem.data(), mem.length());
270 uint32_t key = 0;
271 uint32_t value = 0;
272 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
273 switch (fld.id) {
274 case protos::SysStats::MeminfoValue::kKeyFieldNumber:
275 key = fld.as_uint32();
276 break;
277 case protos::SysStats::MeminfoValue::kValueFieldNumber:
278 value = fld.as_uint32();
279 break;
280 }
281 }
282 if (PERFETTO_UNLIKELY(key >= meminfo_strs_id_.size())) {
283 PERFETTO_ELOG("MemInfo key %d is not recognized.", key);
284 return;
285 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100286 context_->event_tracker->PushCounter(ts, value, meminfo_strs_id_[key], 0,
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100287 RefType::kNoRef);
288}
289
290void ProtoTraceParser::ParseVmStat(uint64_t ts, TraceBlobView stat) {
291 ProtoDecoder decoder(stat.data(), stat.length());
292 uint32_t key = 0;
293 uint32_t value = 0;
294 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
295 switch (fld.id) {
296 case protos::SysStats::VmstatValue::kKeyFieldNumber:
297 key = fld.as_uint32();
298 break;
299 case protos::SysStats::VmstatValue::kValueFieldNumber:
300 value = fld.as_uint32();
301 break;
302 }
303 }
304 if (PERFETTO_UNLIKELY(key >= vmstat_strs_id_.size())) {
305 PERFETTO_ELOG("VmStat key %d is not recognized.", key);
306 return;
307 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100308 context_->event_tracker->PushCounter(ts, value, vmstat_strs_id_[key], 0,
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100309 RefType::kNoRef);
310}
311
312void ProtoTraceParser::ParseCpuTimes(uint64_t ts, TraceBlobView cpu_times) {
313 ProtoDecoder decoder(cpu_times.data(), cpu_times.length());
314 uint64_t cpu = 0;
315 uint32_t value = 0;
316 // Speculate on CPU being first.
317 constexpr auto kCpuFieldTag = protozero::proto_utils::MakeTagVarInt(
318 protos::SysStats::CpuTimes::kCpuIdFieldNumber);
319 if (cpu_times.length() > 2 && cpu_times.data()[0] == kCpuFieldTag &&
320 cpu_times.data()[1] < 0x80) {
321 cpu = cpu_times.data()[1];
322 } else {
323 if (!PERFETTO_LIKELY((
324 decoder.FindIntField<protos::SysStats::CpuTimes::kCpuIdFieldNumber>(
325 &cpu)))) {
326 PERFETTO_ELOG("CPU field not found in CpuTimes");
327 return;
328 }
329 }
330
331 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
332 switch (fld.id) {
333 case protos::SysStats::CpuTimes::kUserNsFieldNumber: {
334 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100335 context_->event_tracker->PushCounter(ts, value, cpu_times_user_ns_id_,
336 cpu, RefType::kCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100337 break;
338 }
339 case protos::SysStats::CpuTimes::kUserIceNsFieldNumber: {
340 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100341 context_->event_tracker->PushCounter(
342 ts, value, cpu_times_user_ice_ns_id_, cpu, RefType::kCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100343 break;
344 }
345 case protos::SysStats::CpuTimes::kSystemModeNsFieldNumber: {
346 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100347 context_->event_tracker->PushCounter(
348 ts, value, cpu_times_system_mode_ns_id_, cpu, RefType::kCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100349 break;
350 }
351 case protos::SysStats::CpuTimes::kIdleNsFieldNumber: {
352 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100353 context_->event_tracker->PushCounter(ts, value, cpu_times_idle_ns_id_,
354 cpu, RefType::kCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100355 break;
356 }
357 case protos::SysStats::CpuTimes::kIoWaitNsFieldNumber: {
358 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100359 context_->event_tracker->PushCounter(
360 ts, value, cpu_times_io_wait_ns_id_, cpu, RefType::kCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100361 break;
362 }
363 case protos::SysStats::CpuTimes::kIrqNsFieldNumber: {
364 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100365 context_->event_tracker->PushCounter(ts, value, cpu_times_irq_ns_id_,
366 cpu, RefType::kCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100367 break;
368 }
369 case protos::SysStats::CpuTimes::kSoftirqNsFieldNumber: {
370 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100371 context_->event_tracker->PushCounter(
372 ts, value, cpu_times_softirq_ns_id_, cpu, RefType::kCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100373 break;
374 }
375 default:
376 break;
377 }
378 }
379}
380
Primiano Tuccid933d912018-09-04 09:15:07 +0100381void ProtoTraceParser::ParseProcessTree(TraceBlobView pstree) {
382 ProtoDecoder decoder(pstree.data(), pstree.length());
Isabelle Taylord80932a2018-06-19 17:00:47 +0100383
Isabelle Taylord80932a2018-06-19 17:00:47 +0100384 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100385 const size_t fld_off = pstree.offset_of(fld.data());
Isabelle Taylord80932a2018-06-19 17:00:47 +0100386 switch (fld.id) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100387 case protos::ProcessTree::kProcessesFieldNumber: {
388 ParseProcess(pstree.slice(fld_off, fld.size()));
Isabelle Taylord80932a2018-06-19 17:00:47 +0100389 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100390 }
391 case protos::ProcessTree::kThreadsFieldNumber: {
392 ParseThread(pstree.slice(fld_off, fld.size()));
Isabelle Taylord80932a2018-06-19 17:00:47 +0100393 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100394 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100395 default:
396 break;
397 }
398 }
399 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
400}
401
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700402void ProtoTraceParser::ParseProcessStats(uint64_t ts, TraceBlobView stats) {
403 ProtoDecoder decoder(stats.data(), stats.length());
404
405 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
406 const size_t fld_off = stats.offset_of(fld.data());
407 switch (fld.id) {
408 case protos::ProcessStats::kMemCountersFieldNumber: {
409 ParseProcMemCounters(ts, stats.slice(fld_off, fld.size()));
410 break;
411 }
412 default:
413 break;
414 }
415 }
416 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
417}
418
419void ProtoTraceParser::ParseProcMemCounters(uint64_t ts,
420 TraceBlobView proc_stat) {
421 ProtoDecoder decoder(proc_stat.data(), proc_stat.length());
422 uint32_t pid = 0;
423 // Maps a process counter field it to its value.
424 // E.g., 4 := 1024 -> "mem.rss.anon" := 1024.
425 std::array<uint64_t, kProcMemCounterSize> counter_values{};
426 std::array<uint8_t, kProcMemCounterSize> has_counter{};
427
428 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
429 switch (fld.id) {
430 case protos::ProcessStats::MemCounters::kPidFieldNumber:
431 pid = fld.as_uint32();
432 break;
433 default:
434 if (fld.id < counter_values.size()) {
435 // Memory counters are in KB, keep values in bytes in the trace
436 // processor.
437 counter_values[fld.id] = fld.as_uint64() * 1024;
438 has_counter[fld.id] = 1;
439 } else {
440 PERFETTO_ELOG("Skipping unknown process counters %" PRIu32, fld.id);
441 }
442 }
443 }
444
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000445 UniqueTid utid = context_->process_tracker->UpdateThread(ts, pid, 0);
Lalit Maganti770886a2018-11-16 17:40:21 +0000446 auto opt_upid = context_->storage->GetThread(utid).upid;
447 if (!opt_upid.has_value()) {
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000448 PERFETTO_DLOG("Could not find process associated with utid %" PRIu32
449 " when parsing mem counters.",
450 utid);
Lalit Maganti6fdb9842018-11-12 11:00:00 +0000451 context_->storage->mutable_stats()->mem_counter_no_process++;
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000452 return;
453 }
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700454
455 // Skip field_id 0 (invalid) and 1 (pid).
456 for (size_t field_id = 2; field_id < counter_values.size(); field_id++) {
457 if (!has_counter[field_id])
458 continue;
459
460 // Lookup the interned string id from the field name using the
461 // pre-cached |proc_mem_counter_names_| map.
462 StringId name = proc_mem_counter_names_[field_id];
463 uint64_t value = counter_values[field_id];
Lalit Maganti770886a2018-11-16 17:40:21 +0000464 context_->event_tracker->PushCounter(ts, value, name, opt_upid.value(),
465 RefType::kUpid);
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700466 }
467
468 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
469}
470
Primiano Tuccid933d912018-09-04 09:15:07 +0100471void ProtoTraceParser::ParseThread(TraceBlobView thread) {
472 ProtoDecoder decoder(thread.data(), thread.length());
Isabelle Taylord80932a2018-06-19 17:00:47 +0100473 uint32_t tid = 0;
474 uint32_t tgid = 0;
Isabelle Taylord80932a2018-06-19 17:00:47 +0100475 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
476 switch (fld.id) {
477 case protos::ProcessTree::Thread::kTidFieldNumber:
478 tid = fld.as_uint32();
479 break;
480 case protos::ProcessTree::Thread::kTgidFieldNumber:
481 tgid = fld.as_uint32();
482 break;
Isabelle Taylord80932a2018-06-19 17:00:47 +0100483 default:
484 break;
485 }
486 }
Isabelle Taylora0a22972018-08-03 12:06:12 +0100487 context_->process_tracker->UpdateThread(tid, tgid);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100488
489 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
490}
491
Primiano Tuccid933d912018-09-04 09:15:07 +0100492void ProtoTraceParser::ParseProcess(TraceBlobView process) {
493 ProtoDecoder decoder(process.data(), process.length());
494
Isabelle Taylord80932a2018-06-19 17:00:47 +0100495 uint32_t pid = 0;
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100496 base::StringView process_name;
Primiano Tuccid933d912018-09-04 09:15:07 +0100497
Isabelle Taylord80932a2018-06-19 17:00:47 +0100498 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
499 switch (fld.id) {
500 case protos::ProcessTree::Process::kPidFieldNumber:
501 pid = fld.as_uint32();
502 break;
503 case protos::ProcessTree::Process::kCmdlineFieldNumber:
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100504 if (process_name.empty())
505 process_name = fld.as_string();
Isabelle Taylord80932a2018-06-19 17:00:47 +0100506 break;
507 default:
508 break;
509 }
510 }
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100511 context_->process_tracker->UpdateProcess(pid, process_name);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100512 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
513}
514
Primiano Tuccid933d912018-09-04 09:15:07 +0100515void ProtoTraceParser::ParseFtracePacket(uint32_t cpu,
516 uint64_t timestamp,
517 TraceBlobView ftrace) {
518 ProtoDecoder decoder(ftrace.data(), ftrace.length());
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100519 uint32_t pid = 0;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100520 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
521 switch (fld.id) {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100522 case protos::FtraceEvent::kPidFieldNumber: {
523 pid = fld.as_uint32();
524 break;
525 }
Primiano Tuccid933d912018-09-04 09:15:07 +0100526 case protos::FtraceEvent::kSchedSwitchFieldNumber: {
Lalit Magantidf3e9262018-06-04 17:45:00 +0100527 PERFETTO_DCHECK(timestamp > 0);
Primiano Tuccid933d912018-09-04 09:15:07 +0100528 const size_t fld_off = ftrace.offset_of(fld.data());
529 ParseSchedSwitch(cpu, timestamp, ftrace.slice(fld_off, fld.size()));
Lalit Magantidf3e9262018-06-04 17:45:00 +0100530 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100531 }
Isabelle Taylor14674d42018-09-07 11:33:11 +0100532 case protos::FtraceEvent::kCpuFrequency: {
533 PERFETTO_DCHECK(timestamp > 0);
534 const size_t fld_off = ftrace.offset_of(fld.data());
535 ParseCpuFreq(timestamp, ftrace.slice(fld_off, fld.size()));
536 break;
537 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100538 case protos::FtraceEvent::kPrintFieldNumber: {
539 PERFETTO_DCHECK(timestamp > 0);
540 const size_t fld_off = ftrace.offset_of(fld.data());
Lalit Magantide6267f2018-11-08 12:35:34 +0000541 ParsePrint(cpu, timestamp, pid, ftrace.slice(fld_off, fld.size()));
Hector Dearman947f12a2018-09-11 16:50:36 +0100542 break;
543 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100544 case protos::FtraceEvent::kRssStatFieldNumber: {
545 PERFETTO_DCHECK(timestamp > 0);
546 const size_t fld_off = ftrace.offset_of(fld.data());
547 ParseRssStat(timestamp, pid, ftrace.slice(fld_off, fld.size()));
548 break;
549 }
550 case protos::FtraceEvent::kIonHeapGrow: {
551 PERFETTO_DCHECK(timestamp > 0);
552 const size_t fld_off = ftrace.offset_of(fld.data());
553 ParseIonHeapGrow(timestamp, pid, ftrace.slice(fld_off, fld.size()));
554 break;
555 }
556 case protos::FtraceEvent::kIonHeapShrink: {
557 PERFETTO_DCHECK(timestamp > 0);
558 const size_t fld_off = ftrace.offset_of(fld.data());
559 ParseIonHeapShrink(timestamp, pid, ftrace.slice(fld_off, fld.size()));
560 break;
561 }
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000562 case protos::FtraceEvent::kSignalGenerate: {
563 PERFETTO_DCHECK(timestamp > 0);
564 const size_t fld_off = ftrace.offset_of(fld.data());
565 ParseSignalGenerate(timestamp, ftrace.slice(fld_off, fld.size()));
566 break;
567 }
568 case protos::FtraceEvent::kSignalDeliver: {
569 PERFETTO_DCHECK(timestamp > 0);
570 const size_t fld_off = ftrace.offset_of(fld.data());
571 ParseSignalDeliver(timestamp, pid, ftrace.slice(fld_off, fld.size()));
572 break;
573 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100574
Lalit Magantidf3e9262018-06-04 17:45:00 +0100575 default:
576 break;
577 }
578 }
579 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
580}
581
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000582void ProtoTraceParser::ParseSignalDeliver(uint64_t timestamp,
583 uint32_t pid,
584 TraceBlobView view) {
585 ProtoDecoder decoder(view.data(), view.length());
586 uint32_t sig = 0;
587 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
588 switch (fld.id) {
589 case protos::SignalDeliverFtraceEvent::kSigFieldNumber:
590 sig = fld.as_uint32();
591 break;
592 }
593 }
594 auto* instants = context_->storage->mutable_instants();
595 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
596 instants->AddInstantEvent(timestamp, signal_deliver_id_, sig, utid,
597 RefType::kUtid);
598}
599
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000600// This event has both the pid of the thread that sent the signal and the
601// destination of the signal. Currently storing the pid of the destination.
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000602void ProtoTraceParser::ParseSignalGenerate(uint64_t timestamp,
603 TraceBlobView view) {
604 ProtoDecoder decoder(view.data(), view.length());
605 uint32_t pid = 0;
606 uint32_t sig = 0;
607 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
608 switch (fld.id) {
609 case protos::SignalGenerateFtraceEvent::kPidFieldNumber:
610 pid = fld.as_uint32();
611 break;
612 case protos::SignalGenerateFtraceEvent::kSigFieldNumber:
613 sig = fld.as_uint32();
614 break;
615 }
616 }
617 auto* instants = context_->storage->mutable_instants();
618 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
619 instants->AddInstantEvent(timestamp, signal_generate_id_, sig, utid,
620 RefType::kUtid);
621}
622
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000623void ProtoTraceParser::ParseLowmemoryKill(uint64_t timestamp,
624 TraceBlobView view) {
625 // TODO(taylori): Store the pagecache_size, pagecache_limit and free fields
626 // in an args table
627 ProtoDecoder decoder(view.data(), view.length());
628 uint32_t pid = 0;
629 base::StringView comm;
630 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
631 switch (fld.id) {
632 case protos::LowmemoryKillFtraceEvent::kPidFieldNumber:
633 pid = fld.as_uint32();
634 break;
635 case protos::LowmemoryKillFtraceEvent::kCommFieldNumber:
636 comm = fld.as_string();
637 break;
638 }
639 }
640 // TODO(taylori): Move the comm to the args table once it exists.
641 StringId name = context_->storage->InternString(
642 base::StringView("mem.lmk." + comm.ToStdString()));
643 auto* instants = context_->storage->mutable_instants();
644 // Storing the pid of the event that is lmk-ed.
645 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
646 instants->AddInstantEvent(timestamp, 0, name, utid, RefType::kUtid);
647}
648
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100649void ProtoTraceParser::ParseRssStat(uint64_t timestamp,
650 uint32_t pid,
651 TraceBlobView view) {
652 ProtoDecoder decoder(view.data(), view.length());
653 uint32_t member = 0;
654 uint32_t size = 0;
655 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
656 switch (fld.id) {
657 case protos::RssStatFtraceEvent::kMemberFieldNumber:
658 member = fld.as_uint32();
659 break;
660 case protos::RssStatFtraceEvent::kSizeFieldNumber:
661 size = fld.as_uint32();
662 break;
663 }
664 }
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700665 if (member >= rss_members_.size()) {
666 PERFETTO_ELOG("Unknown member field %" PRIu32 " in rss_stat event", member);
667 return;
668 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100669 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
Lalit Maganti770886a2018-11-16 17:40:21 +0000670 auto opt_upid = context_->storage->GetThread(utid).upid;
671 if (!opt_upid.has_value()) {
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000672 PERFETTO_DLOG("Could not find process associated with utid %" PRIu32
673 " when parsing rss stat.",
674 utid);
Lalit Maganti6fdb9842018-11-12 11:00:00 +0000675 context_->storage->mutable_stats()->rss_stat_no_process++;
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000676 return;
677 }
678
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100679 context_->event_tracker->PushCounter(timestamp, size, rss_members_[member],
Lalit Maganti770886a2018-11-16 17:40:21 +0000680 opt_upid.value(), RefType::kUpid);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100681 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
682}
683
684void ProtoTraceParser::ParseIonHeapGrow(uint64_t timestamp,
685 uint32_t pid,
686 TraceBlobView view) {
687 ProtoDecoder decoder(view.data(), view.length());
688 uint32_t value = 0;
689 // TODO(b/118300811): The heap name pointer cannot be read. Read once it
690 // has been fixed.
691 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
692 switch (fld.id) {
693 case protos::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber:
694 value = fld.as_uint32();
695 break;
696 }
697 }
698 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
699 context_->event_tracker->PushCounter(timestamp, value, ion_heap_grow_id_,
700 utid, RefType::kUtid);
701 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
702}
703
704void ProtoTraceParser::ParseIonHeapShrink(uint64_t timestamp,
705 uint32_t pid,
706 TraceBlobView view) {
707 ProtoDecoder decoder(view.data(), view.length());
708 uint32_t value = 0;
709 // TODO(b/118300811): The heap name pointer cannot be read. Read once it
710 // has been fixed.
711 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
712 switch (fld.id) {
713 case protos::IonHeapShrinkFtraceEvent::kTotalAllocatedFieldNumber:
714 value = fld.as_uint32();
715 break;
716 }
717 }
718 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
719 context_->event_tracker->PushCounter(timestamp, value, ion_heap_shrink_id_,
720 utid, RefType::kUtid);
721 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
722}
723
Isabelle Taylor14674d42018-09-07 11:33:11 +0100724void ProtoTraceParser::ParseCpuFreq(uint64_t timestamp, TraceBlobView view) {
725 ProtoDecoder decoder(view.data(), view.length());
726
Isabelle Taylor15314ea2018-09-19 11:35:19 +0100727 uint32_t cpu_affected = 0;
Isabelle Taylor14674d42018-09-07 11:33:11 +0100728 uint32_t new_freq = 0;
729 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
730 switch (fld.id) {
731 case protos::CpuFrequencyFtraceEvent::kCpuIdFieldNumber:
Isabelle Taylor15314ea2018-09-19 11:35:19 +0100732 cpu_affected = fld.as_uint32();
Isabelle Taylor14674d42018-09-07 11:33:11 +0100733 break;
734 case protos::CpuFrequencyFtraceEvent::kStateFieldNumber:
735 new_freq = fld.as_uint32();
736 break;
737 }
738 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100739 context_->event_tracker->PushCounter(timestamp, new_freq, cpu_freq_name_id_,
740 cpu_affected, RefType::kCpuId);
Isabelle Taylor14674d42018-09-07 11:33:11 +0100741 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
742}
743
Primiano Tucci7e330292018-08-24 19:10:52 +0200744void ProtoTraceParser::ParseSchedSwitch(uint32_t cpu,
745 uint64_t timestamp,
Primiano Tuccid933d912018-09-04 09:15:07 +0100746 TraceBlobView sswitch) {
747 ProtoDecoder decoder(sswitch.data(), sswitch.length());
748
Lalit Magantidf3e9262018-06-04 17:45:00 +0100749 uint32_t prev_pid = 0;
Lalit Maganti35622b72018-06-06 12:03:11 +0100750 uint32_t prev_state = 0;
Lalit Magantifde29042018-10-04 13:28:52 +0100751 base::StringView next_comm;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100752 uint32_t next_pid = 0;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100753 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
754 switch (fld.id) {
755 case protos::SchedSwitchFtraceEvent::kPrevPidFieldNumber:
756 prev_pid = fld.as_uint32();
757 break;
Lalit Maganti35622b72018-06-06 12:03:11 +0100758 case protos::SchedSwitchFtraceEvent::kPrevStateFieldNumber:
759 prev_state = fld.as_uint32();
760 break;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100761 case protos::SchedSwitchFtraceEvent::kNextPidFieldNumber:
762 next_pid = fld.as_uint32();
763 break;
Lalit Magantifde29042018-10-04 13:28:52 +0100764 case protos::SchedSwitchFtraceEvent::kNextCommFieldNumber:
765 next_comm = fld.as_string();
766 break;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100767 default:
768 break;
769 }
770 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100771 context_->event_tracker->PushSchedSwitch(cpu, timestamp, prev_pid, prev_state,
Lalit Magantifde29042018-10-04 13:28:52 +0100772 next_pid, next_comm);
Lalit Magantidf3e9262018-06-04 17:45:00 +0100773 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
774}
775
Hector Dearman947f12a2018-09-11 16:50:36 +0100776void ProtoTraceParser::ParsePrint(uint32_t,
777 uint64_t timestamp,
Lalit Magantide6267f2018-11-08 12:35:34 +0000778 uint32_t pid,
Hector Dearman947f12a2018-09-11 16:50:36 +0100779 TraceBlobView print) {
780 ProtoDecoder decoder(print.data(), print.length());
781
782 base::StringView buf{};
783 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
784 if (fld.id == protos::PrintFtraceEvent::kBufFieldNumber) {
785 buf = fld.as_string();
786 break;
787 }
788 }
789
790 SystraceTracePoint point{};
791 if (!ParseSystraceTracePoint(buf, &point))
792 return;
793
Hector Dearman947f12a2018-09-11 16:50:36 +0100794 switch (point.phase) {
795 case 'B': {
796 StringId name_id = context_->storage->InternString(point.name);
Lalit Magantide6267f2018-11-08 12:35:34 +0000797 context_->slice_tracker->BeginAndroid(timestamp, pid, point.tid,
798 0 /*cat_id*/, name_id);
Hector Dearman947f12a2018-09-11 16:50:36 +0100799 break;
800 }
801
802 case 'E': {
Lalit Magantide6267f2018-11-08 12:35:34 +0000803 context_->slice_tracker->EndAndroid(timestamp, pid, point.tid);
Hector Dearman947f12a2018-09-11 16:50:36 +0100804 break;
805 }
Isabelle Taylor31e04402018-09-19 12:13:25 +0100806
807 case 'C': {
Lalit Magantide6267f2018-11-08 12:35:34 +0000808 UniqueTid utid =
809 context_->process_tracker->UpdateThread(timestamp, point.tid, 0);
Isabelle Taylor31e04402018-09-19 12:13:25 +0100810 StringId name_id = context_->storage->InternString(point.name);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100811 context_->event_tracker->PushCounter(timestamp, point.value, name_id,
812 utid, RefType::kUtid);
Isabelle Taylor31e04402018-09-19 12:13:25 +0100813 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100814 }
815 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
816}
817
Lalit Maganti93b76362018-06-01 03:03:58 +0100818} // namespace trace_processor
819} // namespace perfetto