trace_processor: fix slice view for Android traces
Follow catapult approach to slices in Android traces by mapping
the kernel pids to the pids in print events (i.e. atrace events)
and then using these for end events.
This allows for end events which don't have pids to actually end
the slices properly
Bug: 119002659
Change-Id: I42fc6d441eff5637f8b9b658eeed2f99bab20f07
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 0f5cd2b..815deb1 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -48,14 +48,12 @@
// If str matches '[BEC]\|[0-9]+[\|\n]' set tid_length to the length of
// the number. Otherwise return false.
- if (len < 3 || s[1] != '|')
+ if (s[1] != '|' && s[1] != '\n')
return false;
if (s[0] != 'B' && s[0] != 'E' && s[0] != 'C')
return false;
- size_t tid_length;
- for (size_t i = 2;; i++) {
- if (i >= len)
- return false;
+ size_t tid_length = 0;
+ for (size_t i = 2; i < len; i++) {
if (s[i] == '|' || s[i] == '\n') {
tid_length = i - 2;
break;
@@ -64,8 +62,12 @@
return false;
}
- std::string tid_str(s + 2, tid_length);
- out->tid = static_cast<uint32_t>(std::stoi(tid_str.c_str()));
+ if (tid_length == 0) {
+ out->tid = 0;
+ } else {
+ std::string tid_str(s + 2, tid_length);
+ out->tid = static_cast<uint32_t>(std::stoi(tid_str.c_str()));
+ }
out->phase = s[0];
switch (s[0]) {
@@ -527,7 +529,7 @@
case protos::FtraceEvent::kPrintFieldNumber: {
PERFETTO_DCHECK(timestamp > 0);
const size_t fld_off = ftrace.offset_of(fld.data());
- ParsePrint(cpu, timestamp, ftrace.slice(fld_off, fld.size()));
+ ParsePrint(cpu, timestamp, pid, ftrace.slice(fld_off, fld.size()));
break;
}
case protos::FtraceEvent::kRssStatFieldNumber: {
@@ -755,6 +757,7 @@
void ProtoTraceParser::ParsePrint(uint32_t,
uint64_t timestamp,
+ uint32_t pid,
TraceBlobView print) {
ProtoDecoder decoder(print.data(), print.length());
@@ -770,22 +773,22 @@
if (!ParseSystraceTracePoint(buf, &point))
return;
- UniqueTid utid =
- context_->process_tracker->UpdateThread(timestamp, point.tid, 0);
-
switch (point.phase) {
case 'B': {
StringId name_id = context_->storage->InternString(point.name);
- context_->slice_tracker->Begin(timestamp, utid, 0 /*cat_id*/, name_id);
+ context_->slice_tracker->BeginAndroid(timestamp, pid, point.tid,
+ 0 /*cat_id*/, name_id);
break;
}
case 'E': {
- context_->slice_tracker->End(timestamp, utid);
+ context_->slice_tracker->EndAndroid(timestamp, pid, point.tid);
break;
}
case 'C': {
+ UniqueTid utid =
+ context_->process_tracker->UpdateThread(timestamp, point.tid, 0);
StringId name_id = context_->storage->InternString(point.name);
context_->event_tracker->PushCounter(timestamp, point.value, name_id,
utid, RefType::kUtid);
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
index 2411a01..a9559b8 100644
--- a/src/trace_processor/proto_trace_parser.h
+++ b/src/trace_processor/proto_trace_parser.h
@@ -65,7 +65,10 @@
void ParseProcMemCounters(uint64_t timestamp, TraceBlobView);
void ParseSchedSwitch(uint32_t cpu, uint64_t timestamp, TraceBlobView);
void ParseCpuFreq(uint64_t timestamp, TraceBlobView);
- void ParsePrint(uint32_t cpu, uint64_t timestamp, TraceBlobView);
+ void ParsePrint(uint32_t cpu,
+ uint64_t timestamp,
+ uint32_t pid,
+ TraceBlobView);
void ParseThread(TraceBlobView);
void ParseProcess(TraceBlobView);
void ParseSysStats(uint64_t ts, TraceBlobView);
diff --git a/src/trace_processor/slice_tracker.cc b/src/trace_processor/slice_tracker.cc
index 5760c74..46e5c33 100644
--- a/src/trace_processor/slice_tracker.cc
+++ b/src/trace_processor/slice_tracker.cc
@@ -18,6 +18,7 @@
#include <stdint.h>
+#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_storage.h"
@@ -30,6 +31,17 @@
SliceTracker::~SliceTracker() = default;
+void SliceTracker::BeginAndroid(uint64_t timestamp,
+ uint32_t ftrace_tid,
+ uint32_t atrace_tid,
+ StringId cat,
+ StringId name) {
+ UniqueTid utid =
+ context_->process_tracker->UpdateThread(timestamp, atrace_tid, 0);
+ ftrace_to_atrace_pid_[ftrace_tid] = atrace_tid;
+ Begin(timestamp, utid, cat, name);
+}
+
void SliceTracker::Begin(uint64_t timestamp,
UniqueTid utid,
StringId cat,
@@ -50,6 +62,21 @@
CompleteSlice(utid);
}
+void SliceTracker::EndAndroid(uint64_t timestamp,
+ uint32_t ftrace_tid,
+ uint32_t atrace_tid) {
+ uint32_t actual_tid = ftrace_to_atrace_pid_[ftrace_tid];
+ if (atrace_tid != 0 && atrace_tid != actual_tid) {
+ PERFETTO_DLOG("Mismatched atrace pid %u and looked up pid %u", , atrace_tid,
+ actual_tid);
+ }
+ if (actual_tid == 0)
+ return;
+ UniqueTid utid =
+ context_->process_tracker->UpdateThread(timestamp, actual_tid, 0);
+ End(timestamp, utid);
+}
+
void SliceTracker::End(uint64_t timestamp,
UniqueTid utid,
StringId cat,
diff --git a/src/trace_processor/slice_tracker.h b/src/trace_processor/slice_tracker.h
index 5197527..1c08d6b 100644
--- a/src/trace_processor/slice_tracker.h
+++ b/src/trace_processor/slice_tracker.h
@@ -31,6 +31,12 @@
explicit SliceTracker(TraceProcessorContext*);
~SliceTracker();
+ void BeginAndroid(uint64_t timestamp,
+ uint32_t ftrace_tid,
+ uint32_t atrace_tid,
+ StringId cat,
+ StringId name);
+
void Begin(uint64_t timestamp, UniqueTid utid, StringId cat, StringId name);
void Scoped(uint64_t timestamp,
@@ -39,6 +45,8 @@
StringId name,
uint64_t duration);
+ void EndAndroid(uint64_t timestamp, uint32_t ftrace_tid, uint32_t atrace_tid);
+
void End(uint64_t timestamp,
UniqueTid utid,
StringId opt_cat = {},
@@ -60,6 +68,7 @@
TraceProcessorContext* const context_;
std::unordered_map<UniqueTid, SlicesStack> threads_;
+ std::unordered_map<uint32_t, uint32_t> ftrace_to_atrace_pid_;
};
} // namespace trace_processor