blob: 4174aae924b0f15b86e4c28caa24ce642837acb0 [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
Ryan Savitski717d5542019-03-18 12:00:16 +000019#include <inttypes.h>
Primiano Tucci132a34d2018-09-19 19:34:01 +010020#include <string.h>
21
Lalit Magantidf3e9262018-06-04 17:45:00 +010022#include <string>
23
Primiano Tuccid933d912018-09-04 09:15:07 +010024#include "perfetto/base/logging.h"
Primiano Tuccib02d8dc2019-06-04 11:46:43 +010025#include "perfetto/ext/base/metatrace_events.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010026#include "perfetto/ext/base/optional.h"
27#include "perfetto/ext/base/string_view.h"
28#include "perfetto/ext/base/utils.h"
29#include "perfetto/ext/traced/sys_stats_counters.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010030#include "perfetto/protozero/proto_decoder.h"
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +000031#include "src/trace_processor/args_tracker.h"
Primiano Tuccia270f012019-01-07 20:01:00 +000032#include "src/trace_processor/clock_tracker.h"
Isabelle Taylora97c5f52018-10-23 17:36:12 +010033#include "src/trace_processor/event_tracker.h"
Lalit Maganti1d915a62019-01-07 12:10:42 +000034#include "src/trace_processor/ftrace_descriptors.h"
Florian Mayer438b5ab2019-05-02 11:18:06 +010035#include "src/trace_processor/heap_profile_tracker.h"
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +010036#include "src/trace_processor/metadata.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010037#include "src/trace_processor/process_tracker.h"
Hector Dearman947f12a2018-09-11 16:50:36 +010038#include "src/trace_processor/slice_tracker.h"
Hector Dearmanf31a7032019-03-29 10:05:09 +000039#include "src/trace_processor/syscall_tracker.h"
Lalit Magantid33dc272019-06-06 14:51:45 +010040#include "src/trace_processor/systrace_parser.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010041#include "src/trace_processor/trace_processor_context.h"
Mikhail Khokhlov85a0dd02019-05-17 14:22:28 +010042#include "src/trace_processor/variadic.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010043
Primiano Tuccie5f11682019-03-22 07:21:49 +000044#include "perfetto/common/android_log_constants.pbzero.h"
Raymond Chiu303ed402019-06-20 12:50:04 -070045#include "perfetto/common/gpu_counter_descriptor.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000046#include "perfetto/common/trace_stats.pbzero.h"
Raymond Chiu994a35d2019-06-12 16:37:26 -070047#include "perfetto/ext/base/string_writer.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000048#include "perfetto/trace/android/android_log.pbzero.h"
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +010049#include "perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000050#include "perfetto/trace/clock_snapshot.pbzero.h"
51#include "perfetto/trace/ftrace/ftrace.pbzero.h"
52#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
53#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
54#include "perfetto/trace/ftrace/generic.pbzero.h"
55#include "perfetto/trace/ftrace/kmem.pbzero.h"
56#include "perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
57#include "perfetto/trace/ftrace/mm_event.pbzero.h"
58#include "perfetto/trace/ftrace/oom.pbzero.h"
59#include "perfetto/trace/ftrace/power.pbzero.h"
60#include "perfetto/trace/ftrace/raw_syscalls.pbzero.h"
61#include "perfetto/trace/ftrace/sched.pbzero.h"
62#include "perfetto/trace/ftrace/signal.pbzero.h"
Lalit Magantid33dc272019-06-06 14:51:45 +010063#include "perfetto/trace/ftrace/systrace.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000064#include "perfetto/trace/ftrace/task.pbzero.h"
Raymond Chiu994a35d2019-06-12 16:37:26 -070065#include "perfetto/trace/gpu/gpu_counter_event.pbzero.h"
Eric Seckler56a007d2019-05-02 16:25:14 +010066#include "perfetto/trace/interned_data/interned_data.pbzero.h"
Primiano Tuccib02d8dc2019-06-04 11:46:43 +010067#include "perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000068#include "perfetto/trace/power/battery_counters.pbzero.h"
Lalit Magantie23653a2019-03-27 17:21:42 +000069#include "perfetto/trace/power/power_rails.pbzero.h"
Florian Mayer93d16ec2019-06-05 09:51:58 +010070#include "perfetto/trace/profiling/profile_common.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000071#include "perfetto/trace/profiling/profile_packet.pbzero.h"
72#include "perfetto/trace/ps/process_stats.pbzero.h"
73#include "perfetto/trace/ps/process_tree.pbzero.h"
74#include "perfetto/trace/sys_stats/sys_stats.pbzero.h"
Hector Dearmanf31a7032019-03-29 10:05:09 +000075#include "perfetto/trace/system_info.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000076#include "perfetto/trace/trace.pbzero.h"
77#include "perfetto/trace/trace_packet.pbzero.h"
Eric Seckler56a007d2019-05-02 16:25:14 +010078#include "perfetto/trace/track_event/debug_annotation.pbzero.h"
79#include "perfetto/trace/track_event/task_execution.pbzero.h"
80#include "perfetto/trace/track_event/track_event.pbzero.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010081
82namespace perfetto {
83namespace trace_processor {
84
Lalit Maganti1d915a62019-01-07 12:10:42 +000085namespace {
86
87using protozero::ProtoDecoder;
Lalit Maganti1d915a62019-01-07 12:10:42 +000088
Florian Mayer5716fc12019-06-24 11:50:51 -070089HeapProfileTracker::SourceMapping MakeSourceMapping(
90 const protos::pbzero::Mapping::Decoder& entry) {
91 HeapProfileTracker::SourceMapping src_mapping{};
92 src_mapping.build_id = entry.build_id();
Florian Mayer12655732019-07-02 15:08:26 +010093 src_mapping.exact_offset = entry.exact_offset();
94 src_mapping.start_offset = entry.start_offset();
Florian Mayer5716fc12019-06-24 11:50:51 -070095 src_mapping.start = entry.start();
96 src_mapping.end = entry.end();
97 src_mapping.load_bias = entry.load_bias();
98 src_mapping.name_id = 0;
99 for (auto path_string_id_it = entry.path_string_ids(); path_string_id_it;
100 ++path_string_id_it)
101 src_mapping.name_id = path_string_id_it->as_uint32();
102 return src_mapping;
103}
104
105HeapProfileTracker::SourceFrame MakeSourceFrame(
106 const protos::pbzero::Frame::Decoder& entry) {
107 HeapProfileTracker::SourceFrame src_frame;
108 src_frame.name_id = entry.function_name_id();
109 src_frame.mapping_id = entry.mapping_id();
110 src_frame.rel_pc = entry.rel_pc();
111 return src_frame;
112}
113
114HeapProfileTracker::SourceCallstack MakeSourceCallstack(
115 const protos::pbzero::Callstack::Decoder& entry) {
116 HeapProfileTracker::SourceCallstack src_callstack;
117 for (auto frame_it = entry.frame_ids(); frame_it; ++frame_it)
118 src_callstack.emplace_back(frame_it->as_uint64());
119 return src_callstack;
120}
121
122class ProfilePacketInternLookup : public HeapProfileTracker::InternLookup {
123 public:
124 ProfilePacketInternLookup(
125 ProtoIncrementalState::PacketSequenceState* seq_state,
126 TraceStorage* storage)
127 : seq_state_(seq_state), storage_(storage) {}
128
129 base::Optional<StringId> GetString(
130 HeapProfileTracker::SourceStringId iid) const override {
131 base::Optional<StringId> res;
132 auto* map =
133 seq_state_->GetInternedDataMap<protos::pbzero::InternedString>();
134 auto it = map->find(iid);
135 if (it == map->end()) {
136 PERFETTO_DLOG("Did not find string %" PRIu64 " in %zu elems", iid,
137 map->size());
138 return res;
139 }
140 auto entry = it->second.CreateDecoder();
141 const char* str = reinterpret_cast<const char*>(entry.str().data);
142 res = storage_->InternString(base::StringView(str, entry.str().size));
143 return res;
144 }
145
146 base::Optional<HeapProfileTracker::SourceMapping> GetMapping(
147 HeapProfileTracker::SourceMappingId iid) const override {
148 base::Optional<HeapProfileTracker::SourceMapping> res;
149 auto* map = seq_state_->GetInternedDataMap<protos::pbzero::Mapping>();
150 auto it = map->find(iid);
151 if (it == map->end()) {
152 PERFETTO_DLOG("Did not find mapping %" PRIu64 " in %zu elems", iid,
153 map->size());
154 return res;
155 }
156 auto entry = it->second.CreateDecoder();
157 res = MakeSourceMapping(entry);
158 return res;
159 }
160
161 base::Optional<HeapProfileTracker::SourceFrame> GetFrame(
162 HeapProfileTracker::SourceFrameId iid) const override {
163 base::Optional<HeapProfileTracker::SourceFrame> res;
164 auto* map = seq_state_->GetInternedDataMap<protos::pbzero::Frame>();
165 auto it = map->find(iid);
166 if (it == map->end()) {
167 PERFETTO_DLOG("Did not find frame %" PRIu64 " in %zu elems", iid,
168 map->size());
169 return res;
170 }
171 auto entry = it->second.CreateDecoder();
172 res = MakeSourceFrame(entry);
173 return res;
174 }
175
176 base::Optional<HeapProfileTracker::SourceCallstack> GetCallstack(
177 HeapProfileTracker::SourceCallstackId iid) const override {
178 base::Optional<HeapProfileTracker::SourceCallstack> res;
179 auto* map = seq_state_->GetInternedDataMap<protos::pbzero::Callstack>();
180 auto it = map->find(iid);
181 if (it == map->end()) {
182 PERFETTO_DLOG("Did not find callstack %" PRIu64 " in %zu elems", iid,
183 map->size());
184 return res;
185 }
186 auto entry = it->second.CreateDecoder();
187 res = MakeSourceCallstack(entry);
188 return res;
189 }
190
191 private:
192 ProtoIncrementalState::PacketSequenceState* seq_state_;
193 TraceStorage* storage_;
194};
195
Lalit Maganti1d915a62019-01-07 12:10:42 +0000196} // namespace
197
Primiano Tucci7e330292018-08-24 19:10:52 +0200198ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
Isabelle Taylor15314ea2018-09-19 11:35:19 +0100199 : context_(context),
Lalit Maganti6e9c55e2018-11-29 12:00:39 +0000200 utid_name_id_(context->storage->InternString("utid")),
Lalit Maganti369ea3c2019-03-05 11:09:42 +0000201 sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
Isabelle Tayloraca7a462019-06-20 13:30:52 +0100202 sched_waking_name_id_(context->storage->InternString("sched_waking")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100203 cpu_freq_name_id_(context->storage->InternString("cpufreq")),
Hector Dearman7b794cc2018-11-30 14:35:30 +0000204 cpu_idle_name_id_(context->storage->InternString("cpuidle")),
Sidath Senanayake1f5f93a2019-06-06 22:24:15 +0100205 gpu_freq_name_id_(context->storage->InternString("gpufreq")),
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000206 comm_name_id_(context->storage->InternString("comm")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100207 num_forks_name_id_(context->storage->InternString("num_forks")),
208 num_irq_total_name_id_(context->storage->InternString("num_irq_total")),
209 num_softirq_total_name_id_(
210 context->storage->InternString("num_softirq_total")),
211 num_irq_name_id_(context->storage->InternString("num_irq")),
212 num_softirq_name_id_(context->storage->InternString("num_softirq")),
213 cpu_times_user_ns_id_(
214 context->storage->InternString("cpu.times.user_ns")),
Primiano Tuccie5f11682019-03-22 07:21:49 +0000215 cpu_times_user_nice_ns_id_(
216 context->storage->InternString("cpu.times.user_nice_ns")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100217 cpu_times_system_mode_ns_id_(
218 context->storage->InternString("cpu.times.system_mode_ns")),
219 cpu_times_idle_ns_id_(
220 context->storage->InternString("cpu.times.idle_ns")),
221 cpu_times_io_wait_ns_id_(
222 context->storage->InternString("cpu.times.io_wait_ns")),
223 cpu_times_irq_ns_id_(context->storage->InternString("cpu.times.irq_ns")),
224 cpu_times_softirq_ns_id_(
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100225 context->storage->InternString("cpu.times.softirq_ns")),
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000226 signal_deliver_id_(context->storage->InternString("signal_deliver")),
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100227 signal_generate_id_(context->storage->InternString("signal_generate")),
228 batt_charge_id_(context->storage->InternString("batt.charge_uah")),
229 batt_capacity_id_(context->storage->InternString("batt.capacity_pct")),
230 batt_current_id_(context->storage->InternString("batt.current_ua")),
231 batt_current_avg_id_(
Primiano Tucci44231042018-12-06 21:34:32 +0000232 context->storage->InternString("batt.current.avg_ua")),
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000233 lmk_id_(context->storage->InternString("mem.lmk")),
Primiano Tucci90cdc852018-12-21 10:29:44 +0100234 oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
235 ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
236 ion_change_unknown_id_(
Eric Secklerc93823e2019-06-03 16:49:19 +0100237 context->storage->InternString("mem.ion_change.unknown")),
Primiano Tuccib02d8dc2019-06-04 11:46:43 +0100238 metatrace_id_(context->storage->InternString("metatrace")),
Eric Secklerc93823e2019-06-03 16:49:19 +0100239 task_file_name_args_key_id_(
240 context->storage->InternString("task.posted_from.file_name")),
241 task_function_name_args_key_id_(
Eric Seckler0bc0d402019-06-06 14:49:45 +0100242 context->storage->InternString("task.posted_from.function_name")) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100243 for (const auto& name : BuildMeminfoCounterNames()) {
244 meminfo_strs_id_.emplace_back(context->storage->InternString(name));
245 }
246 for (const auto& name : BuildVmstatCounterNames()) {
247 vmstat_strs_id_.emplace_back(context->storage->InternString(name));
248 }
Lalit Maganti6820abc2019-01-21 11:12:23 +0000249 rss_members_.emplace_back(context->storage->InternString("mem.rss.file"));
250 rss_members_.emplace_back(context->storage->InternString("mem.rss.anon"));
Lalit Maganti5a95df22019-01-24 13:28:36 +0000251 rss_members_.emplace_back(context->storage->InternString("mem.swap"));
Lalit Maganti6820abc2019-01-21 11:12:23 +0000252 rss_members_.emplace_back(context->storage->InternString("mem.rss.shmem"));
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100253 rss_members_.emplace_back(
Lalit Maganti6820abc2019-01-21 11:12:23 +0000254 context->storage->InternString("mem.rss.unknown")); // Keep this last.
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700255
Primiano Tuccie5f11682019-03-22 07:21:49 +0000256 using ProcessStats = protos::pbzero::ProcessStats;
Lalit Maganti41c98922019-01-23 19:35:58 +0000257 proc_stats_process_names_[ProcessStats::Process::kVmSizeKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700258 context->storage->InternString("mem.virt");
Lalit Maganti41c98922019-01-23 19:35:58 +0000259 proc_stats_process_names_[ProcessStats::Process::kVmRssKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700260 context->storage->InternString("mem.rss");
Lalit Maganti41c98922019-01-23 19:35:58 +0000261 proc_stats_process_names_[ProcessStats::Process::kRssAnonKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700262 context->storage->InternString("mem.rss.anon");
Lalit Maganti41c98922019-01-23 19:35:58 +0000263 proc_stats_process_names_[ProcessStats::Process::kRssFileKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700264 context->storage->InternString("mem.rss.file");
Lalit Maganti41c98922019-01-23 19:35:58 +0000265 proc_stats_process_names_[ProcessStats::Process::kRssShmemKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700266 context->storage->InternString("mem.rss.shmem");
Lalit Maganti41c98922019-01-23 19:35:58 +0000267 proc_stats_process_names_[ProcessStats::Process::kVmSwapKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700268 context->storage->InternString("mem.swap");
Lalit Maganti41c98922019-01-23 19:35:58 +0000269 proc_stats_process_names_[ProcessStats::Process::kVmLockedKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700270 context->storage->InternString("mem.locked");
Lalit Maganti41c98922019-01-23 19:35:58 +0000271 proc_stats_process_names_[ProcessStats::Process::kVmHwmKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700272 context->storage->InternString("mem.rss.watermark");
Lalit Maganti41c98922019-01-23 19:35:58 +0000273 proc_stats_process_names_[ProcessStats::Process::kOomScoreAdjFieldNumber] =
274 oom_score_adj_id_;
Lalit Magantia824c332019-01-23 17:55:58 +0000275
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000276 mm_event_counter_names_ = {
277 {MmEventCounterNames(
278 context->storage->InternString("mem.mm.min_flt.count"),
279 context->storage->InternString("mem.mm.min_flt.max_lat"),
280 context->storage->InternString("mem.mm.min_flt.avg_lat")),
281 MmEventCounterNames(
282 context->storage->InternString("mem.mm.maj_flt.count"),
283 context->storage->InternString("mem.mm.maj_flt.max_lat"),
284 context->storage->InternString("mem.mm.maj_flt.avg_lat")),
285 MmEventCounterNames(
286 context->storage->InternString("mem.mm.read_io.count"),
287 context->storage->InternString("mem.mm.read_io.max_lat"),
288 context->storage->InternString("mem.mm.read_io.avg_lat")),
289 MmEventCounterNames(
290 context->storage->InternString("mem.mm.compaction.count"),
291 context->storage->InternString("mem.mm.compaction.max_lat"),
292 context->storage->InternString("mem.mm.compaction.avg_lat")),
293 MmEventCounterNames(
294 context->storage->InternString("mem.mm.reclaim.count"),
295 context->storage->InternString("mem.mm.reclaim.max_lat"),
296 context->storage->InternString("mem.mm.reclaim.avg_lat")),
297 MmEventCounterNames(
298 context->storage->InternString("mem.mm.swp_flt.count"),
299 context->storage->InternString("mem.mm.swp_flt.max_lat"),
300 context->storage->InternString("mem.mm.swp_flt.avg_lat")),
301 MmEventCounterNames(
302 context->storage->InternString("mem.mm.kern_alloc.count"),
303 context->storage->InternString("mem.mm.kern_alloc.max_lat"),
304 context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
305
Lalit Magantid86161a2019-02-06 15:07:13 +0000306 // Build the lookup table for the strings inside ftrace events (e.g. the
307 // name of ftrace event fields and the names of their args).
308 for (size_t i = 0; i < GetDescriptorsSize(); i++) {
309 auto* descriptor = GetMessageDescriptorForId(i);
310 if (!descriptor->name) {
311 ftrace_message_strings_.emplace_back();
312 continue;
313 }
314
315 FtraceMessageStrings ftrace_strings;
316 ftrace_strings.message_name_id =
317 context->storage->InternString(descriptor->name);
318
Lalit Maganti3043fbd2019-02-07 10:21:50 +0000319 for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
Lalit Magantid86161a2019-02-06 15:07:13 +0000320 const auto& field = descriptor->fields[fid];
321 if (!field.name)
322 continue;
323 ftrace_strings.field_name_ids[fid] =
324 context->storage->InternString(field.name);
325 }
326 ftrace_message_strings_.emplace_back(ftrace_strings);
327 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100328}
Lalit Maganti93b76362018-06-01 03:03:58 +0100329
Primiano Tucci0d72a312018-08-07 14:42:45 +0100330ProtoTraceParser::~ProtoTraceParser() = default;
331
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700332void ProtoTraceParser::ParseTracePacket(
333 int64_t ts,
334 TraceSorter::TimestampedTracePiece ttp) {
335 PERFETTO_DCHECK(ttp.json_value == nullptr);
336 const TraceBlobView& blob = ttp.blob_view;
337
Primiano Tuccie5f11682019-03-22 07:21:49 +0000338 protos::pbzero::TracePacket::Decoder packet(blob.data(), blob.length());
Lalit Maganti93b76362018-06-01 03:03:58 +0100339
Primiano Tuccie5f11682019-03-22 07:21:49 +0000340 if (packet.has_process_tree())
341 ParseProcessTree(packet.process_tree());
342
343 if (packet.has_process_stats())
344 ParseProcessStats(ts, packet.process_stats());
345
346 if (packet.has_sys_stats())
347 ParseSysStats(ts, packet.sys_stats());
348
349 if (packet.has_battery())
350 ParseBatteryCounters(ts, packet.battery());
351
Lalit Magantie23653a2019-03-27 17:21:42 +0000352 if (packet.has_power_rails())
353 ParsePowerRails(packet.power_rails());
354
Primiano Tuccie5f11682019-03-22 07:21:49 +0000355 if (packet.has_trace_stats())
356 ParseTraceStats(packet.trace_stats());
357
358 if (packet.has_ftrace_stats())
359 ParseFtraceStats(packet.ftrace_stats());
360
361 if (packet.has_clock_snapshot())
362 ParseClockSnapshot(packet.clock_snapshot());
363
364 if (packet.has_android_log())
365 ParseAndroidLogPacket(packet.android_log());
366
367 if (packet.has_profile_packet())
Florian Mayer5716fc12019-06-24 11:50:51 -0700368 ParseProfilePacket(ts, ttp.packet_sequence_state, packet.profile_packet());
Primiano Tuccie5f11682019-03-22 07:21:49 +0000369
Hector Dearmanf31a7032019-03-29 10:05:09 +0000370 if (packet.has_system_info())
371 ParseSystemInfo(packet.system_info());
372
Eric Seckler56a007d2019-05-02 16:25:14 +0100373 if (packet.has_track_event()) {
374 ParseTrackEvent(ts, ttp.thread_timestamp, ttp.packet_sequence_state,
375 packet.track_event());
376 }
377
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +0100378 if (packet.has_chrome_benchmark_metadata()) {
379 ParseChromeBenchmarkMetadata(packet.chrome_benchmark_metadata());
380 }
381
Primiano Tuccib02d8dc2019-06-04 11:46:43 +0100382 if (packet.has_perfetto_metatrace()) {
383 ParseMetatraceEvent(ts, packet.perfetto_metatrace());
384 }
385
Raymond Chiu994a35d2019-06-12 16:37:26 -0700386 if (packet.has_gpu_counter_event()) {
387 ParseGpuCounterEvent(ts, packet.gpu_counter_event());
388 }
389
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000390 // TODO(lalitm): maybe move this to the flush method in the trace processor
391 // once we have it. This may reduce performance in the ArgsTracker though so
392 // needs to be handled carefully.
393 context_->args_tracker->Flush();
Primiano Tuccie5f11682019-03-22 07:21:49 +0000394 PERFETTO_DCHECK(!packet.bytes_left());
Lalit Magantidf3e9262018-06-04 17:45:00 +0100395}
396
Primiano Tuccie5f11682019-03-22 07:21:49 +0000397void ProtoTraceParser::ParseSysStats(int64_t ts, ConstBytes blob) {
398 protos::pbzero::SysStats::Decoder sys_stats(blob.data, blob.size);
399
400 for (auto it = sys_stats.meminfo(); it; ++it) {
401 protos::pbzero::SysStats::MeminfoValue::Decoder mi(it->data(), it->size());
402 auto key = static_cast<size_t>(mi.key());
403 if (PERFETTO_UNLIKELY(key >= meminfo_strs_id_.size())) {
404 PERFETTO_ELOG("MemInfo key %zu is not recognized.", key);
405 context_->storage->IncrementStats(stats::meminfo_unknown_keys);
406 continue;
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100407 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000408 // /proc/meminfo counters are in kB, convert to bytes
409 context_->event_tracker->PushCounter(
410 ts, mi.value() * 1024L, meminfo_strs_id_[key], 0, RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100411 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100412
Primiano Tuccie5f11682019-03-22 07:21:49 +0000413 for (auto it = sys_stats.vmstat(); it; ++it) {
414 protos::pbzero::SysStats::VmstatValue::Decoder vm(it->data(), it->size());
415 auto key = static_cast<size_t>(vm.key());
416 if (PERFETTO_UNLIKELY(key >= vmstat_strs_id_.size())) {
417 PERFETTO_ELOG("VmStat key %zu is not recognized.", key);
418 context_->storage->IncrementStats(stats::vmstat_unknown_keys);
419 continue;
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100420 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000421 context_->event_tracker->PushCounter(ts, vm.value(), vmstat_strs_id_[key],
422 0, RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100423 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100424
Primiano Tuccie5f11682019-03-22 07:21:49 +0000425 for (auto it = sys_stats.cpu_stat(); it; ++it) {
426 protos::pbzero::SysStats::CpuTimes::Decoder ct(it->data(), it->size());
427 if (PERFETTO_UNLIKELY(!ct.has_cpu_id())) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100428 PERFETTO_ELOG("CPU field not found in CpuTimes");
Primiano Tucci0e38a142019-01-07 20:51:09 +0000429 context_->storage->IncrementStats(stats::invalid_cpu_times);
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700430 continue;
Isabelle Taylord80932a2018-06-19 17:00:47 +0100431 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000432 context_->event_tracker->PushCounter(ts, ct.user_ns(),
433 cpu_times_user_ns_id_, ct.cpu_id(),
434 RefType::kRefCpuId);
435 context_->event_tracker->PushCounter(ts, ct.user_ice_ns(),
436 cpu_times_user_nice_ns_id_,
437 ct.cpu_id(), RefType::kRefCpuId);
438 context_->event_tracker->PushCounter(ts, ct.system_mode_ns(),
439 cpu_times_system_mode_ns_id_,
440 ct.cpu_id(), RefType::kRefCpuId);
441 context_->event_tracker->PushCounter(ts, ct.idle_ns(),
442 cpu_times_idle_ns_id_, ct.cpu_id(),
443 RefType::kRefCpuId);
444 context_->event_tracker->PushCounter(ts, ct.io_wait_ns(),
445 cpu_times_io_wait_ns_id_, ct.cpu_id(),
446 RefType::kRefCpuId);
447 context_->event_tracker->PushCounter(ts, ct.irq_ns(), cpu_times_irq_ns_id_,
448 ct.cpu_id(), RefType::kRefCpuId);
449 context_->event_tracker->PushCounter(ts, ct.softirq_ns(),
450 cpu_times_softirq_ns_id_, ct.cpu_id(),
451 RefType::kRefCpuId);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100452 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100453
Primiano Tuccie5f11682019-03-22 07:21:49 +0000454 for (auto it = sys_stats.num_irq(); it; ++it) {
455 protos::pbzero::SysStats::InterruptCount::Decoder ic(it->data(),
456 it->size());
457 context_->event_tracker->PushCounter(ts, ic.count(), num_irq_name_id_,
458 ic.irq(), RefType::kRefIrq);
459 }
460
461 for (auto it = sys_stats.num_softirq(); it; ++it) {
462 protos::pbzero::SysStats::InterruptCount::Decoder ic(it->data(),
463 it->size());
464 context_->event_tracker->PushCounter(ts, ic.count(), num_softirq_name_id_,
465 ic.irq(), RefType::kRefSoftIrq);
466 }
467
468 if (sys_stats.has_num_forks()) {
469 context_->event_tracker->PushCounter(
470 ts, sys_stats.num_forks(), num_forks_name_id_, 0, RefType::kRefNoRef);
471 }
472
473 if (sys_stats.has_num_irq_total()) {
474 context_->event_tracker->PushCounter(ts, sys_stats.num_irq_total(),
475 num_irq_total_name_id_, 0,
476 RefType::kRefNoRef);
477 }
478
479 if (sys_stats.has_num_softirq_total()) {
480 context_->event_tracker->PushCounter(ts, sys_stats.num_softirq_total(),
481 num_softirq_total_name_id_, 0,
482 RefType::kRefNoRef);
483 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100484}
485
Primiano Tuccie5f11682019-03-22 07:21:49 +0000486void ProtoTraceParser::ParseProcessTree(ConstBytes blob) {
487 protos::pbzero::ProcessTree::Decoder ps(blob.data, blob.size);
Primiano Tuccid933d912018-09-04 09:15:07 +0100488
Primiano Tuccie5f11682019-03-22 07:21:49 +0000489 for (auto it = ps.processes(); it; ++it) {
490 protos::pbzero::ProcessTree::Process::Decoder proc(it->data(), it->size());
491 if (!proc.has_cmdline())
492 continue;
493 auto pid = static_cast<uint32_t>(proc.pid());
494 auto ppid = static_cast<uint32_t>(proc.ppid());
Primiano Tuccid933d912018-09-04 09:15:07 +0100495
Lalit Maganti161d1e62019-06-25 16:06:17 +0100496 context_->process_tracker->SetProcessMetadata(pid, ppid,
497 proc.cmdline()->as_string());
Primiano Tuccie5f11682019-03-22 07:21:49 +0000498 }
499
500 for (auto it = ps.threads(); it; ++it) {
501 protos::pbzero::ProcessTree::Thread::Decoder thd(it->data(), it->size());
502 auto tid = static_cast<uint32_t>(thd.tid());
503 auto tgid = static_cast<uint32_t>(thd.tgid());
504 context_->process_tracker->UpdateThread(tid, tgid);
505 }
506}
507
508void ProtoTraceParser::ParseProcessStats(int64_t ts, ConstBytes blob) {
509 protos::pbzero::ProcessStats::Decoder stats(blob.data, blob.size);
510 const auto kOomScoreAdjFieldNumber =
511 protos::pbzero::ProcessStats::Process::kOomScoreAdjFieldNumber;
512 for (auto it = stats.processes(); it; ++it) {
513 // Maps a process counter field it to its value.
514 // E.g., 4 := 1024 -> "mem.rss.anon" := 1024.
515 std::array<int64_t, kProcStatsProcessSize> counter_values{};
516 std::array<bool, kProcStatsProcessSize> has_counter{};
517
518 ProtoDecoder proc(it->data(), it->size());
519 uint32_t pid = 0;
520 for (auto fld = proc.ReadField(); fld.valid(); fld = proc.ReadField()) {
521 if (fld.id() == protos::pbzero::ProcessStats::Process::kPidFieldNumber) {
Isabelle Taylord80932a2018-06-19 17:00:47 +0100522 pid = fld.as_uint32();
Primiano Tuccie5f11682019-03-22 07:21:49 +0000523 continue;
524 }
525 bool is_counter_field = fld.id() < proc_stats_process_names_.size() &&
526 proc_stats_process_names_[fld.id()] != 0;
527 if (is_counter_field) {
528 // Memory counters are in KB, keep values in bytes in the trace
529 // processor.
530 counter_values[fld.id()] = fld.id() == kOomScoreAdjFieldNumber
531 ? fld.as_int64()
532 : fld.as_int64() * 1024;
533 has_counter[fld.id()] = true;
534 } else {
535 context_->storage->IncrementStats(stats::proc_stat_unknown_counters);
536 }
537 }
538
539 // Skip field_id 0 (invalid) and 1 (pid).
540 for (size_t field_id = 2; field_id < counter_values.size(); field_id++) {
541 if (!has_counter[field_id])
542 continue;
543
544 // Lookup the interned string id from the field name using the
545 // pre-cached |proc_stats_process_names_| map.
546 StringId name = proc_stats_process_names_[field_id];
547 int64_t value = counter_values[field_id];
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100548 UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000549 context_->event_tracker->PushCounter(ts, value, name, upid,
550 RefType::kRefUpid);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100551 }
552 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100553}
554
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700555void ProtoTraceParser::ParseFtracePacket(
556 uint32_t cpu,
557 int64_t ts,
558 TraceSorter::TimestampedTracePiece ttp) {
559 PERFETTO_DCHECK(ttp.json_value == nullptr);
560 const TraceBlobView& ftrace = ttp.blob_view;
561
Primiano Tuccid933d912018-09-04 09:15:07 +0100562 ProtoDecoder decoder(ftrace.data(), ftrace.length());
Lalit Maganti1d915a62019-01-07 12:10:42 +0000563 uint64_t raw_pid = 0;
Primiano Tuccic1678872019-03-20 11:30:54 +0000564 if (auto pid_field =
Primiano Tuccie5f11682019-03-22 07:21:49 +0000565 decoder.FindField(protos::pbzero::FtraceEvent::kPidFieldNumber)) {
Primiano Tuccic1678872019-03-20 11:30:54 +0000566 raw_pid = pid_field.as_uint64();
567 } else {
Lalit Maganti1d915a62019-01-07 12:10:42 +0000568 PERFETTO_ELOG("Pid field not found in ftrace packet");
569 return;
570 }
571 uint32_t pid = static_cast<uint32_t>(raw_pid);
572
Primiano Tuccic1678872019-03-20 11:30:54 +0000573 for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
Lalit Maganti1d915a62019-01-07 12:10:42 +0000574 bool is_metadata_field =
Primiano Tuccie5f11682019-03-22 07:21:49 +0000575 fld.id() == protos::pbzero::FtraceEvent::kPidFieldNumber ||
576 fld.id() == protos::pbzero::FtraceEvent::kTimestampFieldNumber;
Lalit Maganti1d915a62019-01-07 12:10:42 +0000577 if (is_metadata_field)
578 continue;
579
Primiano Tuccie5f11682019-03-22 07:21:49 +0000580 ConstBytes data = fld.as_bytes();
581 if (fld.id() == protos::pbzero::FtraceEvent::kGenericFieldNumber) {
582 ParseGenericFtrace(ts, cpu, pid, data);
583 } else if (fld.id() !=
584 protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber) {
585 ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data);
Lalit Maganti1d915a62019-01-07 12:10:42 +0000586 }
587
Primiano Tuccic1678872019-03-20 11:30:54 +0000588 switch (fld.id()) {
Primiano Tuccie5f11682019-03-22 07:21:49 +0000589 case protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber: {
590 ParseSchedSwitch(cpu, ts, data);
Lalit Magantidf3e9262018-06-04 17:45:00 +0100591 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100592 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000593 case protos::pbzero::FtraceEvent::kSchedWakeupFieldNumber: {
594 ParseSchedWakeup(ts, data);
Lalit Maganti369ea3c2019-03-05 11:09:42 +0000595 break;
596 }
Isabelle Tayloraca7a462019-06-20 13:30:52 +0100597 case protos::pbzero::FtraceEvent::kSchedWakingFieldNumber: {
598 ParseSchedWaking(ts, data);
599 break;
600 }
Lalit Maganti637589a2019-07-04 17:25:29 +0100601 case protos::pbzero::FtraceEvent::kSchedProcessFreeFieldNumber: {
602 ParseSchedProcessFree(ts, data);
Lalit Magantib5bd2332019-06-06 14:20:47 +0100603 break;
604 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000605 case protos::pbzero::FtraceEvent::kCpuFrequencyFieldNumber: {
606 ParseCpuFreq(ts, data);
Isabelle Taylor14674d42018-09-07 11:33:11 +0100607 break;
608 }
Sidath Senanayake1f5f93a2019-06-06 22:24:15 +0100609 case protos::pbzero::FtraceEvent::kGpuFrequencyFieldNumber: {
610 ParseGpuFreq(ts, data);
611 break;
612 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000613 case protos::pbzero::FtraceEvent::kCpuIdleFieldNumber: {
614 ParseCpuIdle(ts, data);
Hector Dearman7b794cc2018-11-30 14:35:30 +0000615 break;
616 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000617 case protos::pbzero::FtraceEvent::kPrintFieldNumber: {
618 ParsePrint(cpu, ts, pid, data);
Hector Dearman947f12a2018-09-11 16:50:36 +0100619 break;
620 }
Lalit Magantid33dc272019-06-06 14:51:45 +0100621 case protos::pbzero::FtraceEvent::kZeroFieldNumber: {
622 ParseZero(cpu, ts, pid, data);
623 break;
624 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000625 case protos::pbzero::FtraceEvent::kRssStatFieldNumber: {
626 ParseRssStat(ts, pid, data);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100627 break;
628 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000629 case protos::pbzero::FtraceEvent::kIonHeapGrowFieldNumber: {
630 ParseIonHeapGrowOrShrink(ts, pid, data, true);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100631 break;
632 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000633 case protos::pbzero::FtraceEvent::kIonHeapShrinkFieldNumber: {
634 ParseIonHeapGrowOrShrink(ts, pid, data, false);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100635 break;
636 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000637 case protos::pbzero::FtraceEvent::kSignalGenerateFieldNumber: {
638 ParseSignalGenerate(ts, data);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000639 break;
640 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000641 case protos::pbzero::FtraceEvent::kSignalDeliverFieldNumber: {
642 ParseSignalDeliver(ts, pid, data);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000643 break;
644 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000645 case protos::pbzero::FtraceEvent::kLowmemoryKillFieldNumber: {
646 ParseLowmemoryKill(ts, data);
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000647 break;
648 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000649 case protos::pbzero::FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
650 ParseOOMScoreAdjUpdate(ts, data);
Primiano Tucci44231042018-12-06 21:34:32 +0000651 break;
652 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000653 case protos::pbzero::FtraceEvent::kMmEventRecordFieldNumber: {
654 ParseMmEventRecord(ts, pid, data);
Lalit Magantia824c332019-01-23 17:55:58 +0000655 break;
656 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000657 case protos::pbzero::FtraceEvent::kSysEnterFieldNumber: {
658 ParseSysEvent(ts, pid, true, data);
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000659 break;
660 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000661 case protos::pbzero::FtraceEvent::kSysExitFieldNumber: {
662 ParseSysEvent(ts, pid, false, data);
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000663 break;
664 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000665 case protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber: {
666 ParseTaskNewTask(ts, pid, data);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000667 break;
668 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000669 case protos::pbzero::FtraceEvent::kTaskRenameFieldNumber: {
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100670 ParseTaskRename(data);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000671 break;
672 }
Lalit Magantidf3e9262018-06-04 17:45:00 +0100673 default:
674 break;
675 }
676 }
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000677 // TODO(lalitm): maybe move this to the flush method in the trace processor
678 // once we have it. This may reduce performance in the ArgsTracker though so
679 // needs to be handled carefully.
680 context_->args_tracker->Flush();
681
Primiano Tuccic1678872019-03-20 11:30:54 +0000682 PERFETTO_DCHECK(!decoder.bytes_left());
Lalit Magantidf3e9262018-06-04 17:45:00 +0100683}
684
Primiano Tuccie5f11682019-03-22 07:21:49 +0000685void ProtoTraceParser::ParseSignalDeliver(int64_t ts,
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000686 uint32_t pid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000687 ConstBytes blob) {
688 protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100689 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Lalit Maganti521d97b2019-04-29 13:47:03 +0100690 context_->event_tracker->PushInstant(ts, signal_deliver_id_, sig.sig(), utid,
691 RefType::kRefUtid);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000692}
693
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000694// This event has both the pid of the thread that sent the signal and the
695// destination of the signal. Currently storing the pid of the destination.
Primiano Tuccie5f11682019-03-22 07:21:49 +0000696void ProtoTraceParser::ParseSignalGenerate(int64_t ts, ConstBytes blob) {
697 protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
698
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100699 UniqueTid utid = context_->process_tracker->GetOrCreateThread(
700 static_cast<uint32_t>(sig.pid()));
Lalit Maganti521d97b2019-04-29 13:47:03 +0100701 context_->event_tracker->PushInstant(ts, signal_generate_id_, sig.sig(), utid,
702 RefType::kRefUtid);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000703}
704
Primiano Tuccie5f11682019-03-22 07:21:49 +0000705void ProtoTraceParser::ParseLowmemoryKill(int64_t ts, ConstBytes blob) {
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000706 // TODO(taylori): Store the pagecache_size, pagecache_limit and free fields
707 // in an args table
Primiano Tuccie5f11682019-03-22 07:21:49 +0000708 protos::pbzero::LowmemoryKillFtraceEvent::Decoder lmk(blob.data, blob.size);
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000709
Primiano Tuccie5f11682019-03-22 07:21:49 +0000710 // Store the pid of the event that is lmk-ed.
Lalit Maganti521d97b2019-04-29 13:47:03 +0100711 auto pid = static_cast<uint32_t>(lmk.pid());
Lalit Maganti381cf6a2019-06-17 18:49:32 +0100712 auto opt_utid = context_->process_tracker->GetThreadOrNull(pid);
713
714 // Don't add LMK events for threads we've never seen before. This works around
715 // the case where we get an LMK event after a thread has already been killed.
716 if (!opt_utid)
717 return;
718
719 auto row_id = context_->event_tracker->PushInstant(
720 ts, lmk_id_, 0, opt_utid.value(), RefType::kRefUtid, true);
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000721
722 // Store the comm as an arg.
Lalit Magantid63ec5a2019-03-28 13:55:56 +0000723 auto comm_id = context_->storage->InternString(
724 lmk.has_comm() ? lmk.comm() : base::StringView());
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000725 context_->args_tracker->AddArg(row_id, comm_name_id_, comm_name_id_,
726 Variadic::String(comm_id));
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000727}
728
Primiano Tuccie5f11682019-03-22 07:21:49 +0000729void ProtoTraceParser::ParseRssStat(int64_t ts, uint32_t pid, ConstBytes blob) {
730 protos::pbzero::RssStatFtraceEvent::Decoder rss(blob.data, blob.size);
Primiano Tuccibc560992018-12-06 19:11:45 +0000731 const auto kRssStatUnknown = static_cast<uint32_t>(rss_members_.size()) - 1;
Primiano Tuccie5f11682019-03-22 07:21:49 +0000732 auto member = static_cast<uint32_t>(rss.member());
733 int64_t size = rss.size();
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700734 if (member >= rss_members_.size()) {
Primiano Tucci0e38a142019-01-07 20:51:09 +0000735 context_->storage->IncrementStats(stats::rss_stat_unknown_keys);
Primiano Tuccibc560992018-12-06 19:11:45 +0000736 member = kRssStatUnknown;
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700737 }
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000738
Ioannis Ilkos81bd0ea2019-02-14 15:16:26 +0000739 if (size >= 0) {
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100740 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000741 context_->event_tracker->PushCounter(ts, size, rss_members_[member], utid,
Lalit Maganti521d97b2019-04-29 13:47:03 +0100742 RefType::kRefUtid, true);
Ioannis Ilkos81bd0ea2019-02-14 15:16:26 +0000743 } else {
744 context_->storage->IncrementStats(stats::rss_stat_negative_size);
745 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100746}
747
Primiano Tuccie5f11682019-03-22 07:21:49 +0000748void ProtoTraceParser::ParseIonHeapGrowOrShrink(int64_t ts,
Primiano Tucci90cdc852018-12-21 10:29:44 +0100749 uint32_t pid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000750 ConstBytes blob,
Primiano Tucci90cdc852018-12-21 10:29:44 +0100751 bool grow) {
Primiano Tuccie5f11682019-03-22 07:21:49 +0000752 protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000753 int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
Ioannis Ilkosd4efb702019-05-07 14:24:49 +0100754 // The total_allocated ftrace event reports the value before the
755 // atomic_long_add / sub takes place.
756 int64_t total_bytes = ion.total_allocated() + change_bytes;
Primiano Tucci90cdc852018-12-21 10:29:44 +0100757 StringId global_name_id = ion_total_unknown_id_;
758 StringId change_name_id = ion_change_unknown_id_;
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100759
Primiano Tuccie5f11682019-03-22 07:21:49 +0000760 if (ion.has_heap_name()) {
761 char counter_name[255];
762 base::StringView heap_name = ion.heap_name();
763 snprintf(counter_name, sizeof(counter_name), "mem.ion.%.*s",
764 int(heap_name.size()), heap_name.data());
765 global_name_id = context_->storage->InternString(counter_name);
766 snprintf(counter_name, sizeof(counter_name), "mem.ion_change.%.*s",
767 int(heap_name.size()), heap_name.data());
768 change_name_id = context_->storage->InternString(counter_name);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100769 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000770
Primiano Tucci90cdc852018-12-21 10:29:44 +0100771 // Push the global counter.
Primiano Tuccie5f11682019-03-22 07:21:49 +0000772 context_->event_tracker->PushCounter(ts, total_bytes, global_name_id, 0,
773 RefType::kRefNoRef);
Primiano Tucci90cdc852018-12-21 10:29:44 +0100774
775 // Push the change counter.
776 // TODO(b/121331269): these should really be instant events. For now we
Primiano Tuccicd37b4d2018-12-21 16:33:32 +0100777 // manually reset them to 0 after 1ns.
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100778 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000779 context_->event_tracker->PushCounter(ts, change_bytes, change_name_id, utid,
Primiano Tuccicd37b4d2018-12-21 16:33:32 +0100780 RefType::kRefUtid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000781 context_->event_tracker->PushCounter(ts + 1, 0, change_name_id, utid,
782 RefType::kRefUtid);
Primiano Tucci90cdc852018-12-21 10:29:44 +0100783
784 // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
785 // It is fine as the arguments are the same, but we need to be sure that the
786 // protobuf field id for both are the same.
787 static_assert(
Primiano Tuccie5f11682019-03-22 07:21:49 +0000788 static_cast<int>(
789 protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
790 static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
791 kTotalAllocatedFieldNumber) &&
792 static_cast<int>(
793 protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
794 static_cast<int>(
795 protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
796 static_cast<int>(
797 protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
798 static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
799 kHeapNameFieldNumber),
800 "ION field mismatch");
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100801}
802
Primiano Tuccie5f11682019-03-22 07:21:49 +0000803void ProtoTraceParser::ParseCpuFreq(int64_t ts, ConstBytes blob) {
804 protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
805 uint32_t cpu = freq.cpu_id();
806 uint32_t new_freq = freq.state();
807 context_->event_tracker->PushCounter(ts, new_freq, cpu_freq_name_id_, cpu,
808 RefType::kRefCpuId);
Isabelle Taylor14674d42018-09-07 11:33:11 +0100809}
810
Primiano Tuccie5f11682019-03-22 07:21:49 +0000811void ProtoTraceParser::ParseCpuIdle(int64_t ts, ConstBytes blob) {
812 protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
813 uint32_t cpu = idle.cpu_id();
814 uint32_t new_state = idle.state();
815 context_->event_tracker->PushCounter(ts, new_state, cpu_idle_name_id_, cpu,
816 RefType::kRefCpuId);
Hector Dearman7b794cc2018-11-30 14:35:30 +0000817}
818
Sidath Senanayake1f5f93a2019-06-06 22:24:15 +0100819void ProtoTraceParser::ParseGpuFreq(int64_t ts, ConstBytes blob) {
820 protos::pbzero::GpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
821 uint32_t gpu = freq.gpu_id();
822 uint32_t new_freq = freq.state();
823 context_->event_tracker->PushCounter(ts, new_freq, gpu_freq_name_id_, gpu,
824 RefType::kRefGpuId);
825}
826
Primiano Tuccie5f11682019-03-22 07:21:49 +0000827PERFETTO_ALWAYS_INLINE
Primiano Tucci7e330292018-08-24 19:10:52 +0200828void ProtoTraceParser::ParseSchedSwitch(uint32_t cpu,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000829 int64_t ts,
830 ConstBytes blob) {
831 protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
832 uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
833 uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
834 context_->event_tracker->PushSchedSwitch(
835 cpu, ts, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
836 next_pid, ss.next_comm(), ss.next_prio());
Lalit Magantidf3e9262018-06-04 17:45:00 +0100837}
838
Primiano Tuccie5f11682019-03-22 07:21:49 +0000839void ProtoTraceParser::ParseSchedWakeup(int64_t ts, ConstBytes blob) {
840 protos::pbzero::SchedWakeupFtraceEvent::Decoder sw(blob.data, blob.size);
841 uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
842 StringId name_id = context_->storage->InternString(sw.comm());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100843 auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
Lalit Maganti521d97b2019-04-29 13:47:03 +0100844 context_->event_tracker->PushInstant(ts, sched_wakeup_name_id_, 0 /* value */,
845 utid, RefType::kRefUtid);
Lalit Maganti369ea3c2019-03-05 11:09:42 +0000846}
847
Isabelle Tayloraca7a462019-06-20 13:30:52 +0100848void ProtoTraceParser::ParseSchedWaking(int64_t ts, ConstBytes blob) {
849 protos::pbzero::SchedWakingFtraceEvent::Decoder sw(blob.data, blob.size);
850 uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
851 StringId name_id = context_->storage->InternString(sw.comm());
852 auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
853 context_->event_tracker->PushInstant(ts, sched_waking_name_id_, 0 /* value */,
854 utid, RefType::kRefUtid);
855}
856
Lalit Maganti637589a2019-07-04 17:25:29 +0100857void ProtoTraceParser::ParseSchedProcessFree(int64_t ts, ConstBytes blob) {
858 protos::pbzero::SchedProcessFreeFtraceEvent::Decoder ex(blob.data, blob.size);
Lalit Magantib5bd2332019-06-06 14:20:47 +0100859 uint32_t pid = static_cast<uint32_t>(ex.pid());
Lalit Maganti637589a2019-07-04 17:25:29 +0100860 context_->process_tracker->EndThread(ts, pid);
Lalit Magantib5bd2332019-06-06 14:20:47 +0100861}
862
Primiano Tuccie5f11682019-03-22 07:21:49 +0000863void ProtoTraceParser::ParseTaskNewTask(int64_t ts,
Primiano Tucci711de1f2019-03-04 11:11:33 +0000864 uint32_t source_tid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000865 ConstBytes blob) {
866 protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
867 uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
868 uint32_t new_tid = static_cast<uint32_t>(evt.pid());
869 StringId new_comm = context_->storage->InternString(evt.comm());
Primiano Tucci711de1f2019-03-04 11:11:33 +0000870 auto* proc_tracker = context_->process_tracker.get();
871
872 // task_newtask is raised both in the case of a new process creation (fork()
873 // family) and thread creation (clone(CLONE_THREAD, ...)).
874 static const uint32_t kCloneThread = 0x00010000; // From kernel's sched.h.
875 if ((clone_flags & kCloneThread) == 0) {
876 // This is a plain-old fork() or equivalent.
Lalit Maganti161d1e62019-06-25 16:06:17 +0100877 proc_tracker->StartNewProcess(ts, new_tid, new_comm);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000878 return;
879 }
880
881 // This is a pthread_create or similar. Bind the two threads together, so
882 // they get resolved to the same process.
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100883 auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000884 auto new_utid = proc_tracker->StartNewThread(ts, new_tid, new_comm);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000885 proc_tracker->AssociateThreads(source_utid, new_utid);
886}
887
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100888void ProtoTraceParser::ParseTaskRename(ConstBytes blob) {
Primiano Tuccie5f11682019-03-22 07:21:49 +0000889 protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
890 uint32_t tid = static_cast<uint32_t>(evt.pid());
891 StringId comm = context_->storage->InternString(evt.newcomm());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100892 context_->process_tracker->UpdateThreadName(tid, comm);
Lalit Maganti161d1e62019-06-25 16:06:17 +0100893 context_->process_tracker->UpdateProcessNameFromThreadName(tid, comm);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000894}
895
Hector Dearman947f12a2018-09-11 16:50:36 +0100896void ProtoTraceParser::ParsePrint(uint32_t,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000897 int64_t ts,
Lalit Magantide6267f2018-11-08 12:35:34 +0000898 uint32_t pid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000899 ConstBytes blob) {
900 protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
Lalit Magantid33dc272019-06-06 14:51:45 +0100901 context_->systrace_parser->ParsePrintEvent(ts, pid, evt.buf());
902}
Hector Dearman947f12a2018-09-11 16:50:36 +0100903
Lalit Magantid33dc272019-06-06 14:51:45 +0100904void ProtoTraceParser::ParseZero(uint32_t,
905 int64_t ts,
906 uint32_t pid,
907 ConstBytes blob) {
908 protos::pbzero::ZeroFtraceEvent::Decoder evt(blob.data, blob.size);
909 uint32_t tgid = static_cast<uint32_t>(evt.pid());
910 context_->systrace_parser->ParseZeroEvent(ts, pid, evt.flag(), evt.name(),
911 tgid, evt.value());
Hector Dearman947f12a2018-09-11 16:50:36 +0100912}
913
Primiano Tuccie5f11682019-03-22 07:21:49 +0000914void ProtoTraceParser::ParseBatteryCounters(int64_t ts, ConstBytes blob) {
915 protos::pbzero::BatteryCounters::Decoder evt(blob.data, blob.size);
916 if (evt.has_charge_counter_uah()) {
917 context_->event_tracker->PushCounter(
918 ts, evt.charge_counter_uah(), batt_charge_id_, 0, RefType::kRefNoRef);
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100919 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000920 if (evt.has_capacity_percent()) {
921 context_->event_tracker->PushCounter(
922 ts, static_cast<double>(evt.capacity_percent()), batt_capacity_id_, 0,
923 RefType::kRefNoRef);
924 }
925 if (evt.has_current_ua()) {
926 context_->event_tracker->PushCounter(ts, evt.current_ua(), batt_current_id_,
927 0, RefType::kRefNoRef);
928 }
929 if (evt.has_current_avg_ua()) {
930 context_->event_tracker->PushCounter(
931 ts, evt.current_avg_ua(), batt_current_avg_id_, 0, RefType::kRefNoRef);
932 }
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100933}
934
Lalit Magantie23653a2019-03-27 17:21:42 +0000935void ProtoTraceParser::ParsePowerRails(ConstBytes blob) {
936 protos::pbzero::PowerRails::Decoder evt(blob.data, blob.size);
937 if (evt.has_rail_descriptor()) {
938 for (auto it = evt.rail_descriptor(); it; ++it) {
939 protos::pbzero::PowerRails::RailDescriptor::Decoder desc(it->data(),
940 it->size());
Ryan Savitski2ee3f972019-04-02 15:16:38 +0100941 uint32_t idx = desc.index();
942 if (PERFETTO_UNLIKELY(idx > 256)) {
943 PERFETTO_DLOG("Skipping excessively large power_rail index %" PRIu32,
944 idx);
945 continue;
946 }
Lalit Magantie23653a2019-03-27 17:21:42 +0000947 if (power_rails_strs_id_.size() <= idx)
948 power_rails_strs_id_.resize(idx + 1);
949 char counter_name[255];
950 snprintf(counter_name, sizeof(counter_name), "power.%.*s_uws",
951 int(desc.rail_name().size), desc.rail_name().data);
952 power_rails_strs_id_[idx] = context_->storage->InternString(counter_name);
953 }
954 }
955
956 if (evt.has_energy_data()) {
957 for (auto it = evt.energy_data(); it; ++it) {
958 protos::pbzero::PowerRails::EnergyData::Decoder desc(it->data(),
959 it->size());
960 if (desc.index() < power_rails_strs_id_.size()) {
961 int64_t ts = static_cast<int64_t>(desc.timestamp_ms()) * 1000000;
962 context_->event_tracker->PushCounter(ts, desc.energy(),
963 power_rails_strs_id_[desc.index()],
964 0, RefType::kRefNoRef);
965 } else {
966 context_->storage->IncrementStats(stats::power_rail_unknown_index);
967 }
968 }
969 }
970}
971
Primiano Tuccie5f11682019-03-22 07:21:49 +0000972void ProtoTraceParser::ParseOOMScoreAdjUpdate(int64_t ts, ConstBytes blob) {
973 protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
974 blob.size);
975 // The int16_t static cast is because older version of the on-device tracer
976 // had a bug on negative varint encoding (b/120618641).
977 int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
Ioannis Ilkosc8dd9b42019-05-08 22:41:39 +0100978 uint32_t tid = static_cast<uint32_t>(evt.pid());
979 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
980 context_->event_tracker->PushCounter(ts, oom_adj, oom_score_adj_id_, utid,
981 RefType::kRefUtid, true);
Primiano Tucci44231042018-12-06 21:34:32 +0000982}
983
Primiano Tuccie5f11682019-03-22 07:21:49 +0000984void ProtoTraceParser::ParseMmEventRecord(int64_t ts,
985 uint32_t pid,
986 ConstBytes blob) {
987 protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
988 uint32_t type = evt.type();
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100989 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000990
Lalit Magantia824c332019-01-23 17:55:58 +0000991 if (type >= mm_event_counter_names_.size()) {
992 context_->storage->IncrementStats(stats::mm_unknown_type);
993 return;
994 }
995
996 const auto& counter_names = mm_event_counter_names_[type];
Primiano Tuccie5f11682019-03-22 07:21:49 +0000997 context_->event_tracker->PushCounter(ts, evt.count(), counter_names.count,
Lalit Maganti521d97b2019-04-29 13:47:03 +0100998 utid, RefType::kRefUtid, true);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000999 context_->event_tracker->PushCounter(ts, evt.max_lat(), counter_names.max_lat,
Lalit Maganti521d97b2019-04-29 13:47:03 +01001000 utid, RefType::kRefUtid, true);
Primiano Tuccie5f11682019-03-22 07:21:49 +00001001 context_->event_tracker->PushCounter(ts, evt.avg_lat(), counter_names.avg_lat,
Lalit Maganti521d97b2019-04-29 13:47:03 +01001002 utid, RefType::kRefUtid, true);
Lalit Magantia824c332019-01-23 17:55:58 +00001003}
1004
Hector Dearmanbd6cd472019-02-13 16:42:52 +00001005void ProtoTraceParser::ParseSysEvent(int64_t ts,
1006 uint32_t pid,
1007 bool is_enter,
Primiano Tuccie5f11682019-03-22 07:21:49 +00001008 ConstBytes blob) {
1009 protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
1010 uint32_t syscall_num = static_cast<uint32_t>(evt.id());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +01001011 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Hector Dearmanf31a7032019-03-29 10:05:09 +00001012
Hector Dearmanbd6cd472019-02-13 16:42:52 +00001013 if (is_enter) {
Hector Dearmanf31a7032019-03-29 10:05:09 +00001014 context_->syscall_tracker->Enter(ts, utid, syscall_num);
Hector Dearmanbd6cd472019-02-13 16:42:52 +00001015 } else {
Hector Dearmanf31a7032019-03-29 10:05:09 +00001016 context_->syscall_tracker->Exit(ts, utid, syscall_num);
Hector Dearmanbd6cd472019-02-13 16:42:52 +00001017 }
1018
1019 // We are reusing the same function for sys_enter and sys_exit.
1020 // It is fine as the arguments are the same, but we need to be sure that the
1021 // protobuf field id for both are the same.
Primiano Tuccie5f11682019-03-22 07:21:49 +00001022 static_assert(
1023 static_cast<int>(protos::pbzero::SysEnterFtraceEvent::kIdFieldNumber) ==
1024 static_cast<int>(protos::pbzero::SysExitFtraceEvent::kIdFieldNumber),
1025 "field mismatch");
Hector Dearmanbd6cd472019-02-13 16:42:52 +00001026}
1027
Primiano Tuccie5f11682019-03-22 07:21:49 +00001028void ProtoTraceParser::ParseGenericFtrace(int64_t ts,
Lalit Magantie87cc812019-01-10 15:20:06 +00001029 uint32_t cpu,
Lalit Maganti1d915a62019-01-07 12:10:42 +00001030 uint32_t tid,
Primiano Tuccie5f11682019-03-22 07:21:49 +00001031 ConstBytes blob) {
1032 protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
1033 StringId event_id = context_->storage->InternString(evt.event_name());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +01001034 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
Lalit Maganti1d915a62019-01-07 12:10:42 +00001035 RowId row_id = context_->storage->mutable_raw_events()->AddRawEvent(
Primiano Tuccie5f11682019-03-22 07:21:49 +00001036 ts, event_id, cpu, utid);
Lalit Maganti1d915a62019-01-07 12:10:42 +00001037
Primiano Tuccie5f11682019-03-22 07:21:49 +00001038 for (auto it = evt.field(); it; ++it) {
1039 protos::pbzero::GenericFtraceEvent::Field::Decoder fld(it->data(),
1040 it->size());
1041 auto field_name_id = context_->storage->InternString(fld.name());
1042 if (fld.has_int_value()) {
1043 context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
1044 Variadic::Integer(fld.int_value()));
1045 } else if (fld.has_uint_value()) {
1046 context_->args_tracker->AddArg(
1047 row_id, field_name_id, field_name_id,
1048 Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
1049 } else if (fld.has_str_value()) {
1050 StringId str_value = context_->storage->InternString(fld.str_value());
1051 context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
1052 Variadic::String(str_value));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001053 }
1054 }
1055}
1056
1057void ProtoTraceParser::ParseTypedFtraceToRaw(uint32_t ftrace_id,
Primiano Tuccie5f11682019-03-22 07:21:49 +00001058 int64_t ts,
Lalit Magantie87cc812019-01-10 15:20:06 +00001059 uint32_t cpu,
Lalit Maganti1d915a62019-01-07 12:10:42 +00001060 uint32_t tid,
Primiano Tuccie5f11682019-03-22 07:21:49 +00001061 ConstBytes blob) {
1062 ProtoDecoder decoder(blob.data, blob.size);
Lalit Maganti1d915a62019-01-07 12:10:42 +00001063 if (ftrace_id >= GetDescriptorsSize()) {
1064 PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
1065 ftrace_id);
1066 return;
1067 }
Lalit Magantid86161a2019-02-06 15:07:13 +00001068
Lalit Maganti1d915a62019-01-07 12:10:42 +00001069 MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
Lalit Magantid86161a2019-02-06 15:07:13 +00001070 const auto& message_strings = ftrace_message_strings_[ftrace_id];
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +01001071 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
Lalit Maganti1d915a62019-01-07 12:10:42 +00001072 RowId raw_event_id = context_->storage->mutable_raw_events()->AddRawEvent(
Primiano Tuccie5f11682019-03-22 07:21:49 +00001073 ts, message_strings.message_name_id, cpu, utid);
Primiano Tuccic1678872019-03-20 11:30:54 +00001074 for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
1075 if (PERFETTO_UNLIKELY(fld.id() >= kMaxFtraceEventFields)) {
Ryan Savitski717d5542019-03-18 12:00:16 +00001076 PERFETTO_DLOG(
Primiano Tuccic1678872019-03-20 11:30:54 +00001077 "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
1078 fld.id());
Ryan Savitski717d5542019-03-18 12:00:16 +00001079 continue;
1080 }
Primiano Tuccic1678872019-03-20 11:30:54 +00001081 ProtoSchemaType type = m->fields[fld.id()].type;
1082 StringId name_id = message_strings.field_name_ids[fld.id()];
Lalit Maganti1d915a62019-01-07 12:10:42 +00001083 switch (type) {
1084 case ProtoSchemaType::kUint32:
1085 case ProtoSchemaType::kInt32:
1086 case ProtoSchemaType::kUint64:
1087 case ProtoSchemaType::kInt64:
1088 case ProtoSchemaType::kFixed64:
1089 case ProtoSchemaType::kFixed32:
1090 case ProtoSchemaType::kSfixed32:
1091 case ProtoSchemaType::kSfixed64:
1092 case ProtoSchemaType::kSint32:
1093 case ProtoSchemaType::kSint64:
1094 case ProtoSchemaType::kBool:
1095 case ProtoSchemaType::kEnum: {
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001096 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
Primiano Tuccic1678872019-03-20 11:30:54 +00001097 Variadic::Integer(fld.as_int64()));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001098 break;
1099 }
1100 case ProtoSchemaType::kString:
1101 case ProtoSchemaType::kBytes: {
1102 StringId value = context_->storage->InternString(fld.as_string());
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001103 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
1104 Variadic::String(value));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001105 break;
1106 }
Primiano Tuccic1678872019-03-20 11:30:54 +00001107 case ProtoSchemaType::kDouble: {
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001108 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
Primiano Tuccic1678872019-03-20 11:30:54 +00001109 Variadic::Real(fld.as_double()));
1110 break;
1111 }
1112 case ProtoSchemaType::kFloat: {
1113 context_->args_tracker->AddArg(
1114 raw_event_id, name_id, name_id,
1115 Variadic::Real(static_cast<double>(fld.as_float())));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001116 break;
1117 }
1118 case ProtoSchemaType::kUnknown:
1119 case ProtoSchemaType::kGroup:
1120 case ProtoSchemaType::kMessage:
1121 PERFETTO_DLOG("Could not store %s as a field in args table.",
1122 ProtoSchemaToString(type));
1123 break;
1124 }
1125 }
1126}
1127
Primiano Tuccie5f11682019-03-22 07:21:49 +00001128void ProtoTraceParser::ParseClockSnapshot(ConstBytes blob) {
1129 protos::pbzero::ClockSnapshot::Decoder evt(blob.data, blob.size);
Primiano Tuccia270f012019-01-07 20:01:00 +00001130 int64_t clock_boottime = 0;
1131 int64_t clock_monotonic = 0;
1132 int64_t clock_realtime = 0;
Primiano Tuccie5f11682019-03-22 07:21:49 +00001133 for (auto it = evt.clocks(); it; ++it) {
1134 protos::pbzero::ClockSnapshot::Clock::Decoder clk(it->data(), it->size());
1135 if (clk.type() == protos::pbzero::ClockSnapshot::Clock::BOOTTIME) {
1136 clock_boottime = static_cast<int64_t>(clk.timestamp());
1137 } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::REALTIME) {
1138 clock_realtime = static_cast<int64_t>(clk.timestamp());
1139 } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::MONOTONIC) {
1140 clock_monotonic = static_cast<int64_t>(clk.timestamp());
Primiano Tuccia270f012019-01-07 20:01:00 +00001141 }
1142 }
Primiano Tuccia270f012019-01-07 20:01:00 +00001143
1144 // Usually these snapshots come all together.
1145 PERFETTO_DCHECK(clock_boottime > 0 && clock_monotonic > 0 &&
1146 clock_realtime > 0);
1147
1148 if (clock_boottime <= 0) {
1149 PERFETTO_ELOG("ClockSnapshot has an invalid BOOTTIME (%" PRId64 ")",
1150 clock_boottime);
Primiano Tucci0e38a142019-01-07 20:51:09 +00001151 context_->storage->IncrementStats(stats::invalid_clock_snapshots);
Primiano Tuccia270f012019-01-07 20:01:00 +00001152 return;
1153 }
1154
1155 auto* ct = context_->clock_tracker.get();
1156
1157 // |clock_boottime| is used as the reference trace time.
1158 ct->SyncClocks(ClockDomain::kBootTime, clock_boottime, clock_boottime);
1159
1160 if (clock_monotonic > 0)
1161 ct->SyncClocks(ClockDomain::kMonotonic, clock_monotonic, clock_boottime);
1162
1163 if (clock_realtime > 0)
1164 ct->SyncClocks(ClockDomain::kRealTime, clock_realtime, clock_boottime);
1165}
1166
Primiano Tuccie5f11682019-03-22 07:21:49 +00001167void ProtoTraceParser::ParseAndroidLogPacket(ConstBytes blob) {
1168 protos::pbzero::AndroidLogPacket::Decoder packet(blob.data, blob.size);
1169 for (auto it = packet.events(); it; ++it)
1170 ParseAndroidLogEvent(it->as_bytes());
Primiano Tuccia270f012019-01-07 20:01:00 +00001171
Primiano Tuccie5f11682019-03-22 07:21:49 +00001172 if (packet.has_stats())
1173 ParseAndroidLogStats(packet.stats());
Primiano Tuccia270f012019-01-07 20:01:00 +00001174}
1175
Primiano Tuccie5f11682019-03-22 07:21:49 +00001176void ProtoTraceParser::ParseAndroidLogEvent(ConstBytes blob) {
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001177 // TODO(primiano): Add events and non-stringified fields to the "raw" table.
Primiano Tuccie5f11682019-03-22 07:21:49 +00001178 protos::pbzero::AndroidLogPacket::LogEvent::Decoder evt(blob.data, blob.size);
1179 int64_t ts = static_cast<int64_t>(evt.timestamp());
1180 uint32_t pid = static_cast<uint32_t>(evt.pid());
1181 uint32_t tid = static_cast<uint32_t>(evt.tid());
1182 uint8_t prio = static_cast<uint8_t>(evt.prio());
Lalit Magantid63ec5a2019-03-28 13:55:56 +00001183 StringId tag_id = context_->storage->InternString(
1184 evt.has_tag() ? evt.tag() : base::StringView());
1185 StringId msg_id = context_->storage->InternString(
1186 evt.has_message() ? evt.message() : base::StringView());
Primiano Tuccie5f11682019-03-22 07:21:49 +00001187
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001188 char arg_msg[4096];
1189 char* arg_str = &arg_msg[0];
1190 *arg_str = '\0';
1191 auto arg_avail = [&arg_msg, &arg_str]() {
1192 return sizeof(arg_msg) - static_cast<size_t>(arg_str - arg_msg);
1193 };
Primiano Tuccie5f11682019-03-22 07:21:49 +00001194 for (auto it = evt.args(); it; ++it) {
1195 protos::pbzero::AndroidLogPacket::LogEvent::Arg::Decoder arg(it->data(),
1196 it->size());
1197 if (!arg.has_name())
1198 continue;
1199 arg_str +=
1200 snprintf(arg_str, arg_avail(),
1201 " %.*s=", static_cast<int>(arg.name().size), arg.name().data);
1202 if (arg.has_string_value()) {
1203 arg_str += snprintf(arg_str, arg_avail(), "\"%.*s\"",
1204 static_cast<int>(arg.string_value().size),
1205 arg.string_value().data);
1206 } else if (arg.has_int_value()) {
1207 arg_str += snprintf(arg_str, arg_avail(), "%" PRId64, arg.int_value());
1208 } else if (arg.has_float_value()) {
1209 arg_str += snprintf(arg_str, arg_avail(), "%f",
1210 static_cast<double>(arg.float_value()));
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001211 }
1212 }
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001213
1214 if (prio == 0)
Primiano Tuccie5f11682019-03-22 07:21:49 +00001215 prio = protos::pbzero::AndroidLogPriority::PRIO_INFO;
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001216
1217 if (arg_str != &arg_msg[0]) {
1218 PERFETTO_DCHECK(!msg_id);
1219 // Skip the first space char (" foo=1 bar=2" -> "foo=1 bar=2").
1220 msg_id = context_->storage->InternString(&arg_msg[1]);
1221 }
1222 UniquePid utid = tid ? context_->process_tracker->UpdateThread(tid, pid) : 0;
Hector Dearmanba43f602019-01-29 14:36:11 +00001223 base::Optional<int64_t> opt_trace_time =
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001224 context_->clock_tracker->ToTraceTime(ClockDomain::kRealTime, ts);
Hector Dearmanba43f602019-01-29 14:36:11 +00001225 if (!opt_trace_time)
1226 return;
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001227
1228 // Log events are NOT required to be sorted by trace_time. The virtual table
1229 // will take care of sorting on-demand.
Hector Dearmanba43f602019-01-29 14:36:11 +00001230 context_->storage->mutable_android_log()->AddLogEvent(
1231 opt_trace_time.value(), utid, prio, tag_id, msg_id);
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001232}
1233
Primiano Tuccie5f11682019-03-22 07:21:49 +00001234void ProtoTraceParser::ParseAndroidLogStats(ConstBytes blob) {
1235 protos::pbzero::AndroidLogPacket::Stats::Decoder evt(blob.data, blob.size);
1236 if (evt.has_num_failed()) {
1237 context_->storage->SetStats(stats::android_log_num_failed,
1238 static_cast<int64_t>(evt.num_failed()));
1239 }
1240
1241 if (evt.has_num_skipped()) {
1242 context_->storage->SetStats(stats::android_log_num_skipped,
1243 static_cast<int64_t>(evt.num_skipped()));
1244 }
1245
1246 if (evt.has_num_total()) {
1247 context_->storage->SetStats(stats::android_log_num_total,
1248 static_cast<int64_t>(evt.num_total()));
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001249 }
1250}
1251
Primiano Tuccie5f11682019-03-22 07:21:49 +00001252void ProtoTraceParser::ParseTraceStats(ConstBytes blob) {
1253 protos::pbzero::TraceStats::Decoder evt(blob.data, blob.size);
1254 auto* storage = context_->storage.get();
1255 storage->SetStats(stats::traced_producers_connected,
1256 static_cast<int64_t>(evt.producers_connected()));
1257 storage->SetStats(stats::traced_data_sources_registered,
1258 static_cast<int64_t>(evt.data_sources_registered()));
1259 storage->SetStats(stats::traced_data_sources_seen,
1260 static_cast<int64_t>(evt.data_sources_seen()));
1261 storage->SetStats(stats::traced_tracing_sessions,
1262 static_cast<int64_t>(evt.tracing_sessions()));
1263 storage->SetStats(stats::traced_total_buffers,
1264 static_cast<int64_t>(evt.total_buffers()));
1265 storage->SetStats(stats::traced_chunks_discarded,
1266 static_cast<int64_t>(evt.chunks_discarded()));
1267 storage->SetStats(stats::traced_patches_discarded,
1268 static_cast<int64_t>(evt.patches_discarded()));
Primiano Tucci0e38a142019-01-07 20:51:09 +00001269
Primiano Tucci0e38a142019-01-07 20:51:09 +00001270 int buf_num = 0;
Primiano Tuccie5f11682019-03-22 07:21:49 +00001271 for (auto it = evt.buffer_stats(); it; ++it, ++buf_num) {
1272 protos::pbzero::TraceStats::BufferStats::Decoder buf(it->data(),
1273 it->size());
1274 storage->SetIndexedStats(stats::traced_buf_buffer_size, buf_num,
1275 static_cast<int64_t>(buf.buffer_size()));
1276 storage->SetIndexedStats(stats::traced_buf_bytes_written, buf_num,
1277 static_cast<int64_t>(buf.bytes_written()));
1278 storage->SetIndexedStats(stats::traced_buf_bytes_overwritten, buf_num,
1279 static_cast<int64_t>(buf.bytes_overwritten()));
1280 storage->SetIndexedStats(stats::traced_buf_bytes_read, buf_num,
1281 static_cast<int64_t>(buf.bytes_read()));
1282 storage->SetIndexedStats(stats::traced_buf_padding_bytes_written, buf_num,
1283 static_cast<int64_t>(buf.padding_bytes_written()));
1284 storage->SetIndexedStats(stats::traced_buf_padding_bytes_cleared, buf_num,
1285 static_cast<int64_t>(buf.padding_bytes_cleared()));
1286 storage->SetIndexedStats(stats::traced_buf_chunks_written, buf_num,
1287 static_cast<int64_t>(buf.chunks_written()));
1288 storage->SetIndexedStats(stats::traced_buf_chunks_rewritten, buf_num,
1289 static_cast<int64_t>(buf.chunks_rewritten()));
1290 storage->SetIndexedStats(stats::traced_buf_chunks_overwritten, buf_num,
1291 static_cast<int64_t>(buf.chunks_overwritten()));
1292 storage->SetIndexedStats(stats::traced_buf_chunks_discarded, buf_num,
1293 static_cast<int64_t>(buf.chunks_discarded()));
1294 storage->SetIndexedStats(stats::traced_buf_chunks_read, buf_num,
1295 static_cast<int64_t>(buf.chunks_read()));
1296 storage->SetIndexedStats(
1297 stats::traced_buf_chunks_committed_out_of_order, buf_num,
1298 static_cast<int64_t>(buf.chunks_committed_out_of_order()));
1299 storage->SetIndexedStats(stats::traced_buf_write_wrap_count, buf_num,
1300 static_cast<int64_t>(buf.write_wrap_count()));
1301 storage->SetIndexedStats(stats::traced_buf_patches_succeeded, buf_num,
1302 static_cast<int64_t>(buf.patches_succeeded()));
1303 storage->SetIndexedStats(stats::traced_buf_patches_failed, buf_num,
1304 static_cast<int64_t>(buf.patches_failed()));
1305 storage->SetIndexedStats(stats::traced_buf_readaheads_succeeded, buf_num,
1306 static_cast<int64_t>(buf.readaheads_succeeded()));
1307 storage->SetIndexedStats(stats::traced_buf_readaheads_failed, buf_num,
1308 static_cast<int64_t>(buf.readaheads_failed()));
Primiano Tucci0e38a142019-01-07 20:51:09 +00001309 }
Primiano Tucci0e38a142019-01-07 20:51:09 +00001310}
1311
Primiano Tuccie5f11682019-03-22 07:21:49 +00001312void ProtoTraceParser::ParseFtraceStats(ConstBytes blob) {
1313 protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
1314 size_t phase =
1315 evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE ? 1 : 0;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001316
Primiano Tuccie5f11682019-03-22 07:21:49 +00001317 // This code relies on the fact that each ftrace_cpu_XXX_end event is
1318 // just after the corresponding ftrace_cpu_XXX_begin event.
1319 static_assert(
1320 stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
1321 1 &&
1322 stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
1323 "ftrace_cpu_XXX stats definition are messed up");
1324
1325 auto* storage = context_->storage.get();
1326 for (auto it = evt.cpu_stats(); it; ++it) {
1327 protos::pbzero::FtraceCpuStats::Decoder cpu_stats(it->data(), it->size());
1328 int cpu = static_cast<int>(cpu_stats.cpu());
1329 storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
1330 static_cast<int64_t>(cpu_stats.entries()));
1331 storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
1332 static_cast<int64_t>(cpu_stats.overrun()));
1333 storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
1334 cpu,
1335 static_cast<int64_t>(cpu_stats.commit_overrun()));
1336 storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
1337 static_cast<int64_t>(cpu_stats.bytes_read()));
Lalit Maganti08ca56e2019-04-03 11:04:51 +01001338
1339 // oldest_event_ts can often be set to very high values, possibly because
1340 // of wrapping. Ensure that we are not overflowing to avoid ubsan
1341 // complaining.
1342 double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
1343 if (oldest_event_ts >= std::numeric_limits<int64_t>::max()) {
1344 storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
1345 cpu, std::numeric_limits<int64_t>::max());
1346 } else {
1347 storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
1348 cpu, static_cast<int64_t>(oldest_event_ts));
1349 }
1350
Primiano Tuccie5f11682019-03-22 07:21:49 +00001351 storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
1352 static_cast<int64_t>(cpu_stats.now_ts() * 1e9));
1353 storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
1354 cpu,
1355 static_cast<int64_t>(cpu_stats.dropped_events()));
1356 storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
1357 static_cast<int64_t>(cpu_stats.read_events()));
Primiano Tucci0e38a142019-01-07 20:51:09 +00001358 }
Primiano Tucci0e38a142019-01-07 20:51:09 +00001359}
1360
Florian Mayer5716fc12019-06-24 11:50:51 -07001361void ProtoTraceParser::ParseProfilePacket(
1362 int64_t ts,
1363 ProtoIncrementalState::PacketSequenceState* sequence_state,
1364 ConstBytes blob) {
Primiano Tuccie5f11682019-03-22 07:21:49 +00001365 protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001366
Primiano Tuccie5f11682019-03-22 07:21:49 +00001367 for (auto it = packet.strings(); it; ++it) {
Florian Mayerd0ee6322019-06-07 12:15:48 +01001368 protos::pbzero::InternedString::Decoder entry(it->data(), it->size());
Primiano Tuccie5f11682019-03-22 07:21:49 +00001369
1370 const char* str = reinterpret_cast<const char*>(entry.str().data);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001371 auto str_id = context_->storage->InternString(
1372 base::StringView(str, entry.str().size));
Florian Mayer981b2742019-06-14 15:07:18 +01001373 context_->heap_profile_tracker->AddString(entry.iid(), str_id);
Hector Dearmandd639792019-01-31 15:04:59 +00001374 }
Florian Mayer438b5ab2019-05-02 11:18:06 +01001375
1376 for (auto it = packet.mappings(); it; ++it) {
Florian Mayer93d16ec2019-06-05 09:51:58 +01001377 protos::pbzero::Mapping::Decoder entry(it->data(), it->size());
Florian Mayer5716fc12019-06-24 11:50:51 -07001378 HeapProfileTracker::SourceMapping src_mapping = MakeSourceMapping(entry);
Florian Mayer981b2742019-06-14 15:07:18 +01001379 context_->heap_profile_tracker->AddMapping(entry.iid(), src_mapping);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001380 }
1381
1382 for (auto it = packet.frames(); it; ++it) {
Florian Mayer93d16ec2019-06-05 09:51:58 +01001383 protos::pbzero::Frame::Decoder entry(it->data(), it->size());
Florian Mayer5716fc12019-06-24 11:50:51 -07001384 HeapProfileTracker::SourceFrame src_frame = MakeSourceFrame(entry);
Florian Mayer981b2742019-06-14 15:07:18 +01001385 context_->heap_profile_tracker->AddFrame(entry.iid(), src_frame);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001386 }
1387
1388 for (auto it = packet.callstacks(); it; ++it) {
Florian Mayer93d16ec2019-06-05 09:51:58 +01001389 protos::pbzero::Callstack::Decoder entry(it->data(), it->size());
Florian Mayer5716fc12019-06-24 11:50:51 -07001390 HeapProfileTracker::SourceCallstack src_callstack =
1391 MakeSourceCallstack(entry);
Florian Mayer981b2742019-06-14 15:07:18 +01001392 context_->heap_profile_tracker->AddCallstack(entry.iid(), src_callstack);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001393 }
1394
1395 for (auto it = packet.process_dumps(); it; ++it) {
1396 protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(
1397 it->data(), it->size());
1398
1399 int pid = static_cast<int>(entry.pid());
1400
1401 if (entry.buffer_corrupted())
1402 context_->storage->IncrementIndexedStats(
1403 stats::heapprofd_buffer_corrupted, pid);
1404 if (entry.buffer_overran())
1405 context_->storage->IncrementIndexedStats(stats::heapprofd_buffer_overran,
1406 pid);
1407 if (entry.rejected_concurrent())
1408 context_->storage->IncrementIndexedStats(
1409 stats::heapprofd_rejected_concurrent, pid);
1410
1411 for (auto sample_it = entry.samples(); sample_it; ++sample_it) {
1412 protos::pbzero::ProfilePacket::HeapSample::Decoder sample(
1413 sample_it->data(), sample_it->size());
1414
1415 HeapProfileTracker::SourceAllocation src_allocation;
1416 src_allocation.pid = entry.pid();
Florian Mayer12c89992019-05-14 13:03:10 +01001417 src_allocation.timestamp = ts;
Florian Mayer438b5ab2019-05-02 11:18:06 +01001418 src_allocation.callstack_id = sample.callstack_id();
1419 src_allocation.self_allocated = sample.self_allocated();
1420 src_allocation.self_freed = sample.self_freed();
1421 src_allocation.alloc_count = sample.alloc_count();
1422 src_allocation.free_count = sample.free_count();
1423
Florian Mayer981b2742019-06-14 15:07:18 +01001424 context_->heap_profile_tracker->StoreAllocation(src_allocation);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001425 }
1426 }
Florian Mayerbee52132019-05-02 13:59:56 +01001427 if (!packet.continued()) {
Florian Mayer5716fc12019-06-24 11:50:51 -07001428 PERFETTO_CHECK(sequence_state);
1429 ProfilePacketInternLookup intern_lookup(sequence_state,
1430 context_->storage.get());
1431 context_->heap_profile_tracker->FinalizeProfile(&intern_lookup);
Florian Mayerbee52132019-05-02 13:59:56 +01001432 }
Hector Dearmandd639792019-01-31 15:04:59 +00001433}
1434
Hector Dearmanf31a7032019-03-29 10:05:09 +00001435void ProtoTraceParser::ParseSystemInfo(ConstBytes blob) {
1436 protos::pbzero::SystemInfo::Decoder packet(blob.data, blob.size);
1437 if (packet.has_utsname()) {
1438 ConstBytes utsname_blob = packet.utsname();
1439 protos::pbzero::Utsname::Decoder utsname(utsname_blob.data,
1440 utsname_blob.size);
1441 base::StringView machine = utsname.machine();
1442 if (machine == "aarch64" || machine == "armv8l") {
1443 context_->syscall_tracker->SetArchitecture(kAarch64);
1444 } else if (machine == "x86_64") {
1445 context_->syscall_tracker->SetArchitecture(kX86_64);
1446 } else {
1447 PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
1448 }
1449 }
1450}
1451
Eric Seckler56a007d2019-05-02 16:25:14 +01001452void ProtoTraceParser::ParseTrackEvent(
1453 int64_t ts,
1454 int64_t /*tts*/,
1455 ProtoIncrementalState::PacketSequenceState* sequence_state,
1456 ConstBytes blob) {
1457 protos::pbzero::TrackEvent::Decoder event(blob.data, blob.size);
1458
1459 const auto legacy_event_blob = event.legacy_event();
1460 protos::pbzero::TrackEvent::LegacyEvent::Decoder legacy_event(
1461 legacy_event_blob.data, legacy_event_blob.size);
1462
1463 // TODO(eseckler): This legacy event field will eventually be replaced by
1464 // fields in TrackEvent itself.
1465 if (PERFETTO_UNLIKELY(!legacy_event.has_phase())) {
1466 PERFETTO_ELOG("TrackEvent without phase");
1467 return;
1468 }
1469
1470 ProcessTracker* procs = context_->process_tracker.get();
1471 TraceStorage* storage = context_->storage.get();
1472 SliceTracker* slice_tracker = context_->slice_tracker.get();
1473
1474 uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
1475 uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
1476 if (legacy_event.has_pid_override())
1477 pid = static_cast<uint32_t>(legacy_event.pid_override());
1478 if (legacy_event.has_tid_override())
1479 tid = static_cast<uint32_t>(legacy_event.tid_override());
1480 UniqueTid utid = procs->UpdateThread(tid, pid);
1481
Florian Mayer5716fc12019-06-24 11:50:51 -07001482 std::vector<uint64_t> category_iids;
Eric Seckler56a007d2019-05-02 16:25:14 +01001483 for (auto it = event.category_iids(); it; ++it) {
Florian Mayer5716fc12019-06-24 11:50:51 -07001484 category_iids.push_back(it->as_uint64());
Eric Seckler56a007d2019-05-02 16:25:14 +01001485 }
1486
1487 StringId category_id = 0;
1488
Sidath Senanayake1f5f93a2019-06-06 22:24:15 +01001489 // If there's a single category, we can avoid building a concatenated
1490 // string.
Eric Seckler56a007d2019-05-02 16:25:14 +01001491 if (PERFETTO_LIKELY(category_iids.size() == 1)) {
1492 auto* map =
1493 sequence_state->GetInternedDataMap<protos::pbzero::EventCategory>();
1494 auto cat_view_it = map->find(category_iids[0]);
1495 if (cat_view_it == map->end()) {
Florian Mayer5716fc12019-06-24 11:50:51 -07001496 PERFETTO_ELOG("Could not find category interning entry for ID %" PRIu64,
Eric Seckler56a007d2019-05-02 16:25:14 +01001497 category_iids[0]);
1498 } else {
1499 // If the name is already in the pool, no need to decode it again.
1500 if (cat_view_it->second.storage_refs) {
1501 category_id = cat_view_it->second.storage_refs->name_id;
1502 } else {
1503 auto cat = cat_view_it->second.CreateDecoder();
1504 category_id = storage->InternString(cat.name());
1505 // Avoid having to decode & look up the name again in the future.
1506 cat_view_it->second.storage_refs =
1507 ProtoIncrementalState::StorageReferences<
1508 protos::pbzero::EventCategory>{category_id};
1509 }
1510 }
1511 } else if (category_iids.size() > 1) {
1512 auto* map =
1513 sequence_state->GetInternedDataMap<protos::pbzero::EventCategory>();
1514 // We concatenate the category strings together since we currently only
1515 // support a single "cat" column.
1516 // TODO(eseckler): Support multi-category events in the table schema.
1517 std::string categories;
Florian Mayer5716fc12019-06-24 11:50:51 -07001518 for (uint64_t iid : category_iids) {
Eric Seckler56a007d2019-05-02 16:25:14 +01001519 auto cat_view_it = map->find(iid);
1520 if (cat_view_it == map->end()) {
Florian Mayer5716fc12019-06-24 11:50:51 -07001521 PERFETTO_ELOG("Could not find category interning entry for ID %" PRIu64,
1522 iid);
Eric Seckler56a007d2019-05-02 16:25:14 +01001523 continue;
1524 }
1525 auto cat = cat_view_it->second.CreateDecoder();
1526 base::StringView name = cat.name();
1527 if (!categories.empty())
1528 categories.append(",");
1529 categories.append(name.data(), name.size());
1530 }
1531 if (!categories.empty())
1532 category_id = storage->InternString(base::StringView(categories));
1533 } else {
1534 PERFETTO_ELOG("TrackEvent without category");
1535 }
1536
1537 StringId name_id = 0;
1538
1539 if (PERFETTO_LIKELY(legacy_event.name_iid())) {
1540 auto* map =
1541 sequence_state->GetInternedDataMap<protos::pbzero::LegacyEventName>();
1542 auto name_view_it = map->find(legacy_event.name_iid());
1543 if (name_view_it == map->end()) {
Florian Mayer5716fc12019-06-24 11:50:51 -07001544 PERFETTO_ELOG("Could not find event name interning entry for ID %" PRIu64,
Eric Seckler56a007d2019-05-02 16:25:14 +01001545 legacy_event.name_iid());
1546 } else {
1547 // If the name is already in the pool, no need to decode it again.
1548 if (name_view_it->second.storage_refs) {
1549 name_id = name_view_it->second.storage_refs->name_id;
1550 } else {
1551 auto event_name = name_view_it->second.CreateDecoder();
1552 name_id = storage->InternString(event_name.name());
1553 // Avoid having to decode & look up the name again in the future.
1554 name_view_it->second.storage_refs =
1555 ProtoIncrementalState::StorageReferences<
1556 protos::pbzero::LegacyEventName>{name_id};
1557 }
1558 }
1559 }
1560
Eric Seckler87fd11a2019-06-07 15:52:28 +01001561 // TODO(eseckler): Handle thread timestamp/duration, legacy event attributes,
1562 // legacy event types (async S, T, p, F phases, flow events, sample events,
1563 // object events, metadata events, memory dumps, mark events, clock sync
1564 // events, context events, counter events), ...
Eric Seckler56a007d2019-05-02 16:25:14 +01001565
Eric Secklerc93823e2019-06-03 16:49:19 +01001566 auto args_callback = [this, &event, &sequence_state](
1567 ArgsTracker* args_tracker, RowId row) {
1568 for (auto it = event.debug_annotations(); it; ++it) {
1569 ParseDebugAnnotationArgs(it->as_bytes(), sequence_state, args_tracker,
1570 row);
1571 }
1572
1573 if (event.has_task_execution()) {
1574 ParseTaskExecutionArgs(event.task_execution(), sequence_state,
1575 args_tracker, row);
1576 }
1577 };
1578
Eric Secklera0366df2019-06-07 14:42:56 +01001579 using LegacyEvent = protos::pbzero::TrackEvent::LegacyEvent;
1580
Eric Seckler87fd11a2019-06-07 15:52:28 +01001581 int64_t id = 0;
1582 RefType async_ref_type = RefType::kRefGlobalAsyncTrack;
1583 if (legacy_event.has_unscoped_id()) {
1584 id = static_cast<int64_t>(legacy_event.unscoped_id());
1585 } else if (legacy_event.has_global_id()) {
1586 id = static_cast<int64_t>(legacy_event.global_id());
1587 } else if (legacy_event.has_local_id()) {
1588 id = static_cast<int64_t>(legacy_event.local_id());
1589 async_ref_type = RefType::kRefProcessAsyncTrack;
1590 }
1591
1592 StringId scope_id = 0;
1593 if (legacy_event.has_id_scope()) {
1594 scope_id = storage->InternString(legacy_event.id_scope());
1595 }
1596
Eric Seckler56a007d2019-05-02 16:25:14 +01001597 int32_t phase = legacy_event.phase();
1598 switch (static_cast<char>(phase)) {
1599 case 'B': { // TRACE_EVENT_PHASE_BEGIN.
Eric Secklera0366df2019-06-07 14:42:56 +01001600 slice_tracker->Begin(ts, utid, RefType::kRefUtid, category_id, name_id,
Eric Seckler87fd11a2019-06-07 15:52:28 +01001601 /*ref_scope=*/0, args_callback);
Eric Seckler56a007d2019-05-02 16:25:14 +01001602 break;
1603 }
1604 case 'E': { // TRACE_EVENT_PHASE_END.
Eric Secklera0366df2019-06-07 14:42:56 +01001605 slice_tracker->End(ts, utid, RefType::kRefUtid, category_id, name_id,
Eric Seckler87fd11a2019-06-07 15:52:28 +01001606 /*ref_scope=*/0, args_callback);
Eric Seckler56a007d2019-05-02 16:25:14 +01001607 break;
1608 }
1609 case 'X': { // TRACE_EVENT_PHASE_COMPLETE.
1610 auto duration_ns = legacy_event.duration_us() * 1000;
1611 if (duration_ns < 0)
1612 return;
Eric Secklera0366df2019-06-07 14:42:56 +01001613 slice_tracker->Scoped(ts, utid, RefType::kRefUtid, category_id, name_id,
Eric Seckler87fd11a2019-06-07 15:52:28 +01001614 duration_ns, /*ref_scope=*/0, args_callback);
Eric Seckler56a007d2019-05-02 16:25:14 +01001615 break;
1616 }
Eric Secklera0366df2019-06-07 14:42:56 +01001617 case 'i':
Eric Seckler651ca312019-06-05 16:41:51 +01001618 case 'I': { // TRACE_EVENT_PHASE_INSTANT.
Sidath Senanayake1f5f93a2019-06-06 22:24:15 +01001619 // Handle instant events as slices with zero duration, so that they end
1620 // up nested underneath their parent slices.
Eric Seckler0bc0d402019-06-06 14:49:45 +01001621 int64_t duration_ns = 0;
Eric Secklera0366df2019-06-07 14:42:56 +01001622
1623 switch (legacy_event.instant_event_scope()) {
1624 case LegacyEvent::SCOPE_UNSPECIFIED:
1625 case LegacyEvent::SCOPE_THREAD:
1626 slice_tracker->Scoped(ts, utid, RefType::kRefUtid, category_id,
Eric Seckler87fd11a2019-06-07 15:52:28 +01001627 name_id, duration_ns, /*ref_scope=*/0,
1628 args_callback);
Eric Secklera0366df2019-06-07 14:42:56 +01001629 break;
1630 case LegacyEvent::SCOPE_GLOBAL:
1631 slice_tracker->Scoped(ts, /*ref=*/0, RefType::kRefNoRef, category_id,
Eric Seckler87fd11a2019-06-07 15:52:28 +01001632 name_id, duration_ns, /*ref_scope=*/0,
1633 args_callback);
Eric Secklera0366df2019-06-07 14:42:56 +01001634 break;
1635 case LegacyEvent::SCOPE_PROCESS:
1636 slice_tracker->Scoped(ts, procs->GetOrCreateProcess(pid),
1637 RefType::kRefUpid, category_id, name_id,
Eric Seckler87fd11a2019-06-07 15:52:28 +01001638 duration_ns, /*ref_scope=*/0, args_callback);
Eric Secklera0366df2019-06-07 14:42:56 +01001639 break;
1640 default:
1641 PERFETTO_FATAL("Unknown instant event scope: %u",
1642 legacy_event.instant_event_scope());
1643 break;
1644 }
Eric Seckler651ca312019-06-05 16:41:51 +01001645 break;
1646 }
Eric Seckler87fd11a2019-06-07 15:52:28 +01001647 case 'b': { // TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN
1648 slice_tracker->Begin(ts, id, async_ref_type, category_id, name_id,
1649 scope_id, args_callback);
1650 break;
1651 }
1652 case 'e': { // TRACE_EVENT_PHASE_NESTABLE_ASYNC_END
1653 slice_tracker->End(ts, id, async_ref_type, category_id, name_id, scope_id,
1654 args_callback);
1655 break;
1656 }
1657 case 'n': { // TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
1658 // Handle instant events as slices with zero duration, so that they end up
1659 // nested underneath their parent slices.
1660 int64_t duration_ns = 0;
1661 slice_tracker->Scoped(ts, id, async_ref_type, category_id, name_id,
1662 duration_ns, scope_id, args_callback);
1663 break;
1664 }
Eric Seckler56a007d2019-05-02 16:25:14 +01001665 case 'M': { // TRACE_EVENT_PHASE_METADATA (process and thread names).
1666 // For now, we just compare the event name and assume there's a single
1667 // argument in these events with the name of the process/thread.
1668 // TODO(eseckler): Use names from process/thread descriptors instead.
1669 NullTermStringView event_name = storage->GetString(name_id);
1670 PERFETTO_DCHECK(event_name.data());
1671 if (strcmp(event_name.c_str(), "thread_name") == 0) {
1672 auto it = event.debug_annotations();
1673 if (!it)
1674 break;
1675 protos::pbzero::DebugAnnotation::Decoder annotation(it->data(),
1676 it->size());
1677 auto thread_name = annotation.string_value();
1678 if (!thread_name.size)
1679 break;
1680 auto thread_name_id = context_->storage->InternString(thread_name);
1681 procs->UpdateThreadName(tid, thread_name_id);
1682 } else if (strcmp(event_name.c_str(), "process_name") == 0) {
1683 auto it = event.debug_annotations();
1684 if (!it)
1685 break;
1686 protos::pbzero::DebugAnnotation::Decoder annotation(it->data(),
1687 it->size());
1688 auto process_name = annotation.string_value();
1689 if (!process_name.size)
1690 break;
Lalit Maganti161d1e62019-06-25 16:06:17 +01001691 procs->SetProcessMetadata(pid, base::nullopt, process_name);
Eric Seckler56a007d2019-05-02 16:25:14 +01001692 }
1693 break;
1694 }
1695 }
1696}
1697
Eric Secklerc93823e2019-06-03 16:49:19 +01001698void ProtoTraceParser::ParseDebugAnnotationArgs(
1699 ConstBytes debug_annotation,
1700 ProtoIncrementalState::PacketSequenceState* sequence_state,
1701 ArgsTracker* args_tracker,
1702 RowId row) {
1703 protos::pbzero::DebugAnnotation::Decoder annotation(debug_annotation.data,
1704 debug_annotation.size);
Florian Mayer5716fc12019-06-24 11:50:51 -07001705 uint64_t iid = annotation.name_iid();
Eric Secklerc93823e2019-06-03 16:49:19 +01001706 if (!iid)
1707 return;
1708
1709 auto* map =
1710 sequence_state->GetInternedDataMap<protos::pbzero::DebugAnnotationName>();
1711 auto name_view_it = map->find(iid);
1712 if (name_view_it == map->end()) {
1713 PERFETTO_ELOG(
Florian Mayer5716fc12019-06-24 11:50:51 -07001714 "Could not find debug annotation name interning entry for ID %" PRIu64,
1715 iid);
Eric Secklerc93823e2019-06-03 16:49:19 +01001716 return;
1717 }
1718
1719 TraceStorage* storage = context_->storage.get();
1720
1721 StringId name_id = 0;
1722
1723 // If the name is already in the pool, no need to decode it again.
1724 if (name_view_it->second.storage_refs) {
1725 name_id = name_view_it->second.storage_refs->name_id;
1726 } else {
1727 auto name = name_view_it->second.CreateDecoder();
1728 std::string name_prefixed = "debug." + name.name().ToStdString();
1729 name_id = storage->InternString(base::StringView(name_prefixed));
1730 // Avoid having to decode & look up the name again in the future.
1731 name_view_it->second.storage_refs =
1732 ProtoIncrementalState::StorageReferences<
1733 protos::pbzero::DebugAnnotationName>{name_id};
1734 }
1735
1736 if (annotation.has_bool_value()) {
1737 args_tracker->AddArg(row, name_id, name_id,
1738 Variadic::Boolean(annotation.bool_value()));
1739 } else if (annotation.has_uint_value()) {
1740 args_tracker->AddArg(row, name_id, name_id,
1741 Variadic::UnsignedInteger(annotation.uint_value()));
1742 } else if (annotation.has_int_value()) {
1743 args_tracker->AddArg(row, name_id, name_id,
1744 Variadic::Integer(annotation.int_value()));
1745 } else if (annotation.has_double_value()) {
1746 args_tracker->AddArg(row, name_id, name_id,
1747 Variadic::Real(annotation.double_value()));
1748 } else if (annotation.has_string_value()) {
1749 args_tracker->AddArg(
1750 row, name_id, name_id,
1751 Variadic::String(storage->InternString(annotation.string_value())));
1752 } else if (annotation.has_pointer_value()) {
1753 args_tracker->AddArg(row, name_id, name_id,
1754 Variadic::Pointer(annotation.pointer_value()));
1755 } else if (annotation.has_legacy_json_value()) {
1756 args_tracker->AddArg(row, name_id, name_id,
1757 Variadic::String(storage->InternString(
1758 annotation.legacy_json_value())));
1759 } else if (annotation.has_nested_value()) {
1760 auto name = storage->GetString(name_id);
1761 ParseNestedValueArgs(annotation.nested_value(), name, name, args_tracker,
1762 row);
1763 }
1764}
1765
1766void ProtoTraceParser::ParseNestedValueArgs(ConstBytes nested_value,
1767 base::StringView flat_key,
1768 base::StringView key,
1769 ArgsTracker* args_tracker,
1770 RowId row) {
1771 protos::pbzero::DebugAnnotation::NestedValue::Decoder value(
1772 nested_value.data, nested_value.size);
1773 switch (value.nested_type()) {
1774 case protos::pbzero::DebugAnnotation::NestedValue::UNSPECIFIED: {
1775 auto flat_key_id = context_->storage->InternString(flat_key);
1776 auto key_id = context_->storage->InternString(key);
1777 // Leaf value.
1778 if (value.has_bool_value()) {
1779 args_tracker->AddArg(row, flat_key_id, key_id,
1780 Variadic::Boolean(value.bool_value()));
1781 } else if (value.has_int_value()) {
1782 args_tracker->AddArg(row, flat_key_id, key_id,
1783 Variadic::Integer(value.int_value()));
1784 } else if (value.has_double_value()) {
1785 args_tracker->AddArg(row, flat_key_id, key_id,
1786 Variadic::Real(value.double_value()));
1787 } else if (value.has_string_value()) {
1788 args_tracker->AddArg(row, flat_key_id, key_id,
1789 Variadic::String(context_->storage->InternString(
1790 value.string_value())));
1791 }
1792 break;
1793 }
1794 case protos::pbzero::DebugAnnotation::NestedValue::DICT: {
1795 auto key_it = value.dict_keys();
1796 auto value_it = value.dict_values();
1797 for (; key_it && value_it; ++key_it, ++value_it) {
1798 std::string child_name = key_it->as_std_string();
1799 std::string child_flat_key = flat_key.ToStdString() + "." + child_name;
1800 std::string child_key = key.ToStdString() + "." + child_name;
1801 ParseNestedValueArgs(value_it->as_bytes(),
1802 base::StringView(child_flat_key),
1803 base::StringView(child_key), args_tracker, row);
1804 }
1805 break;
1806 }
1807 case protos::pbzero::DebugAnnotation::NestedValue::ARRAY: {
1808 int child_index = 0;
1809 std::string child_flat_key = flat_key.ToStdString();
1810 for (auto value_it = value.array_values(); value_it;
1811 ++value_it, ++child_index) {
1812 std::string child_key =
1813 key.ToStdString() + "[" + std::to_string(child_index) + "]";
1814 ParseNestedValueArgs(value_it->as_bytes(),
1815 base::StringView(child_flat_key),
1816 base::StringView(child_key), args_tracker, row);
1817 }
1818 break;
1819 }
1820 }
1821}
1822
1823void ProtoTraceParser::ParseTaskExecutionArgs(
1824 ConstBytes task_execution,
1825 ProtoIncrementalState::PacketSequenceState* sequence_state,
1826 ArgsTracker* args_tracker,
1827 RowId row) {
1828 protos::pbzero::TaskExecution::Decoder task(task_execution.data,
1829 task_execution.size);
Florian Mayer5716fc12019-06-24 11:50:51 -07001830 uint64_t iid = task.posted_from_iid();
Eric Secklerc93823e2019-06-03 16:49:19 +01001831 if (!iid)
1832 return;
1833
1834 auto* map =
1835 sequence_state->GetInternedDataMap<protos::pbzero::SourceLocation>();
1836 auto location_view_it = map->find(iid);
1837 if (location_view_it == map->end()) {
Florian Mayer5716fc12019-06-24 11:50:51 -07001838 PERFETTO_ELOG(
1839 "Could not find source location interning entry for ID %" PRIu64, iid);
Eric Secklerc93823e2019-06-03 16:49:19 +01001840 return;
1841 }
1842
1843 StringId file_name_id = 0;
1844 StringId function_name_id = 0;
1845
1846 // If the names are already in the pool, no need to decode them again.
1847 if (location_view_it->second.storage_refs) {
1848 file_name_id = location_view_it->second.storage_refs->file_name_id;
1849 function_name_id = location_view_it->second.storage_refs->function_name_id;
1850 } else {
1851 TraceStorage* storage = context_->storage.get();
1852 auto location = location_view_it->second.CreateDecoder();
1853 file_name_id = storage->InternString(location.file_name());
1854 function_name_id = storage->InternString(location.function_name());
1855 // Avoid having to decode & look up the names again in the future.
1856 location_view_it->second.storage_refs =
1857 ProtoIncrementalState::StorageReferences<
1858 protos::pbzero::SourceLocation>{file_name_id, function_name_id};
1859 }
1860
1861 args_tracker->AddArg(row, task_file_name_args_key_id_,
1862 task_file_name_args_key_id_,
1863 Variadic::String(file_name_id));
1864 args_tracker->AddArg(row, task_function_name_args_key_id_,
1865 task_function_name_args_key_id_,
1866 Variadic::String(function_name_id));
1867}
1868
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +01001869void ProtoTraceParser::ParseChromeBenchmarkMetadata(ConstBytes blob) {
1870 TraceStorage* storage = context_->storage.get();
1871 protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
1872 if (packet.has_benchmark_name()) {
1873 auto benchmark_name_id = storage->InternString(packet.benchmark_name());
1874 storage->SetMetadata(metadata::benchmark_name,
1875 Variadic::String(benchmark_name_id));
1876 }
1877 if (packet.has_benchmark_description()) {
1878 auto benchmark_description_id =
1879 storage->InternString(packet.benchmark_description());
1880 storage->SetMetadata(metadata::benchmark_description,
1881 Variadic::String(benchmark_description_id));
1882 }
1883 if (packet.has_label()) {
1884 auto label_id = storage->InternString(packet.label());
1885 storage->SetMetadata(metadata::benchmark_label, Variadic::String(label_id));
1886 }
1887 if (packet.has_story_name()) {
1888 auto story_name_id = storage->InternString(packet.story_name());
1889 storage->SetMetadata(metadata::benchmark_story_name,
1890 Variadic::String(story_name_id));
1891 }
1892 for (auto it = packet.story_tags(); it; ++it) {
1893 auto story_tag_id = storage->InternString(it->as_string());
1894 storage->AppendMetadata(metadata::benchmark_story_tags,
1895 Variadic::String(story_tag_id));
1896 }
1897 if (packet.has_benchmark_start_time_us()) {
1898 storage->SetMetadata(metadata::benchmark_start_time_us,
1899 Variadic::Integer(packet.benchmark_start_time_us()));
1900 }
1901 if (packet.has_story_run_time_us()) {
1902 storage->SetMetadata(metadata::benchmark_story_run_time_us,
1903 Variadic::Integer(packet.story_run_time_us()));
1904 }
1905 if (packet.has_story_run_index()) {
1906 storage->SetMetadata(metadata::benchmark_story_run_index,
1907 Variadic::Integer(packet.story_run_index()));
1908 }
1909 if (packet.has_had_failures()) {
1910 storage->SetMetadata(metadata::benchmark_had_failures,
1911 Variadic::Integer(packet.had_failures()));
1912 }
1913}
1914
Primiano Tuccib02d8dc2019-06-04 11:46:43 +01001915void ProtoTraceParser::ParseMetatraceEvent(int64_t ts, ConstBytes blob) {
1916 protos::pbzero::PerfettoMetatrace::Decoder event(blob.data, blob.size);
1917 auto utid = context_->process_tracker->GetOrCreateThread(event.thread_id());
1918
1919 StringId cat_id = metatrace_id_;
1920 StringId name_id = 0;
1921 char fallback[64];
1922
1923 if (event.has_event_id()) {
1924 auto eid = event.event_id();
1925 if (eid < metatrace::EVENTS_MAX) {
1926 name_id = context_->storage->InternString(metatrace::kEventNames[eid]);
1927 } else {
1928 sprintf(fallback, "Event %d", eid);
1929 name_id = context_->storage->InternString(fallback);
1930 }
Eric Secklera0366df2019-06-07 14:42:56 +01001931 context_->slice_tracker->Scoped(ts, utid, RefType::kRefUtid, cat_id,
1932 name_id, event.event_duration_ns());
Primiano Tuccib02d8dc2019-06-04 11:46:43 +01001933 } else if (event.has_counter_id()) {
1934 auto cid = event.counter_id();
1935 if (cid < metatrace::COUNTERS_MAX) {
1936 name_id = context_->storage->InternString(metatrace::kCounterNames[cid]);
1937 } else {
1938 sprintf(fallback, "Counter %d", cid);
1939 name_id = context_->storage->InternString(fallback);
1940 }
1941 context_->event_tracker->PushCounter(ts, event.counter_value(), name_id,
1942 utid, RefType::kRefUtid);
1943 }
1944
1945 if (event.has_overruns())
1946 context_->storage->IncrementStats(stats::metatrace_overruns);
1947}
1948
Raymond Chiu994a35d2019-06-12 16:37:26 -07001949void ProtoTraceParser::ParseGpuCounterEvent(int64_t ts, ConstBytes blob) {
1950 protos::pbzero::GpuCounterEvent::Decoder event(blob.data, blob.size);
1951
Raymond Chiu303ed402019-06-20 12:50:04 -07001952 protos::pbzero::GpuCounterDescriptor::Decoder desc(event.counter_descriptor());
Raymond Chiu994a35d2019-06-12 16:37:26 -07001953 // Add counter spec to ID map.
Raymond Chiu303ed402019-06-20 12:50:04 -07001954 for (auto it = desc.specs(); it; ++it) {
1955 protos::pbzero::GpuCounterDescriptor_GpuCounterSpec::Decoder spec(it->data(), it->size());
Raymond Chiu994a35d2019-06-12 16:37:26 -07001956 if (!spec.has_counter_id()) {
1957 PERFETTO_ELOG("Counter spec missing counter id");
1958 context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
1959 continue;
1960 }
1961 if (!spec.has_name()) {
1962 context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
1963 continue;
1964 }
1965
1966 auto counter_id = spec.counter_id();
1967 auto name = spec.name();
1968 if (gpu_counter_ids_.find(counter_id) == gpu_counter_ids_.end()) {
1969 gpu_counter_ids_.emplace(
1970 counter_id,
1971 context_->storage->InternString(name));
1972 } else {
1973 // Either counter spec was repeated or it came after counter data.
1974 PERFETTO_ELOG("Duplicated counter spec found. (counter_id=%d, name=%s)",
1975 counter_id,
1976 name.ToStdString().c_str());
1977 context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
1978 }
1979 }
1980
1981 for (auto it = event.counters(); it; ++it) {
1982 protos::pbzero::GpuCounterEvent_GpuCounter::Decoder counter(it->data(), it->size());
Raymond Chiu303ed402019-06-20 12:50:04 -07001983 if (counter.has_counter_id() && (counter.has_int_value() || counter.has_double_value())) {
Raymond Chiu994a35d2019-06-12 16:37:26 -07001984 auto counter_id = counter.counter_id();
Raymond Chiu994a35d2019-06-12 16:37:26 -07001985 // Check missing counter_id
1986 if (gpu_counter_ids_.find(counter_id) == gpu_counter_ids_.end()) {
1987 char buffer[64];
1988 base::StringWriter writer(buffer, sizeof(buffer));
1989 writer.AppendString("gpu_counter(");
1990 writer.AppendUnsignedInt(counter_id);
1991 writer.AppendString(")");
1992 gpu_counter_ids_.emplace(
1993 counter_id,
1994 context_->storage->InternString(writer.GetStringView()));
1995 context_->storage->IncrementStats(stats::gpu_counters_missing_spec);
1996 }
Raymond Chiu303ed402019-06-20 12:50:04 -07001997 if (counter.has_int_value()) {
1998 context_->event_tracker->PushCounter(
1999 ts, counter.int_value(), gpu_counter_ids_[counter_id], 0, RefType::kRefGpuId);
2000 } else {
2001 context_->event_tracker->PushCounter(
2002 ts, counter.double_value(), gpu_counter_ids_[counter_id], 0, RefType::kRefGpuId);
2003 }
Raymond Chiu994a35d2019-06-12 16:37:26 -07002004 }
2005 }
2006}
2007
Lalit Maganti93b76362018-06-01 03:03:58 +01002008} // namespace trace_processor
2009} // namespace perfetto