aboutsummaryrefslogtreecommitdiff
path: root/src/trace_processor/importers/proto/proto_trace_parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/trace_processor/importers/proto/proto_trace_parser.cc')
-rw-r--r--src/trace_processor/importers/proto/proto_trace_parser.cc309
1 files changed, 147 insertions, 162 deletions
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 4c5566d96..796b318a8 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -29,20 +29,22 @@
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/base/uuid.h"
#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/clock_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/heap_profile_tracker.h"
+#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/common/clock_tracker.h"
+#include "src/trace_processor/importers/common/event_tracker.h"
+#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
+#include "src/trace_processor/importers/proto/heap_profile_tracker.h"
+#include "src/trace_processor/importers/proto/metadata_tracker.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/metadata.h"
-#include "src/trace_processor/metadata_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/stack_profile_tracker.h"
+#include "src/trace_processor/importers/proto/perf_sample_tracker.h"
+#include "src/trace_processor/importers/proto/profile_packet_utils.h"
+#include "src/trace_processor/importers/proto/stack_profile_tracker.h"
+#include "src/trace_processor/storage/metadata.h"
#include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/track_tracker.h"
+#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/types/variadic.h"
#include "protos/perfetto/common/trace_stats.pbzero.h"
@@ -52,116 +54,17 @@
#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
+#include "protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
+#include "protos/perfetto/trace/profiling/smaps.pbzero.h"
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/trigger.pbzero.h"
namespace perfetto {
namespace trace_processor {
-namespace {
-
-StackProfileTracker::SourceMapping MakeSourceMapping(
- const protos::pbzero::Mapping::Decoder& entry) {
- StackProfileTracker::SourceMapping src_mapping{};
- src_mapping.build_id = entry.build_id();
- src_mapping.exact_offset = entry.exact_offset();
- src_mapping.start_offset = entry.start_offset();
- src_mapping.start = entry.start();
- src_mapping.end = entry.end();
- src_mapping.load_bias = entry.load_bias();
- for (auto path_string_id_it = entry.path_string_ids(); path_string_id_it;
- ++path_string_id_it)
- src_mapping.name_ids.emplace_back(*path_string_id_it);
- return src_mapping;
-}
-
-StackProfileTracker::SourceFrame MakeSourceFrame(
- const protos::pbzero::Frame::Decoder& entry) {
- StackProfileTracker::SourceFrame src_frame;
- src_frame.name_id = entry.function_name_id();
- src_frame.mapping_id = entry.mapping_id();
- src_frame.rel_pc = entry.rel_pc();
- return src_frame;
-}
-
-StackProfileTracker::SourceCallstack MakeSourceCallstack(
- const protos::pbzero::Callstack::Decoder& entry) {
- StackProfileTracker::SourceCallstack src_callstack;
- for (auto frame_it = entry.frame_ids(); frame_it; ++frame_it)
- src_callstack.emplace_back(*frame_it);
- return src_callstack;
-}
-
-class ProfilePacketInternLookup : public StackProfileTracker::InternLookup {
- public:
- ProfilePacketInternLookup(PacketSequenceStateGeneration* seq_state)
- : seq_state_(seq_state) {}
-
- base::Optional<base::StringView> GetString(
- StackProfileTracker::SourceStringId iid,
- StackProfileTracker::InternedStringType type) const override {
- protos::pbzero::InternedString::Decoder* decoder = nullptr;
- switch (type) {
- case StackProfileTracker::InternedStringType::kBuildId:
- decoder = seq_state_->LookupInternedMessage<
- protos::pbzero::InternedData::kBuildIdsFieldNumber,
- protos::pbzero::InternedString>(iid);
- break;
- case StackProfileTracker::InternedStringType::kFunctionName:
- decoder = seq_state_->LookupInternedMessage<
- protos::pbzero::InternedData::kFunctionNamesFieldNumber,
- protos::pbzero::InternedString>(iid);
- break;
- case StackProfileTracker::InternedStringType::kMappingPath:
- decoder = seq_state_->LookupInternedMessage<
- protos::pbzero::InternedData::kMappingPathsFieldNumber,
- protos::pbzero::InternedString>(iid);
- break;
- }
- if (!decoder)
- return base::nullopt;
- return base::StringView(reinterpret_cast<const char*>(decoder->str().data),
- decoder->str().size);
- }
-
- base::Optional<StackProfileTracker::SourceMapping> GetMapping(
- StackProfileTracker::SourceMappingId iid) const override {
- auto* decoder = seq_state_->LookupInternedMessage<
- protos::pbzero::InternedData::kMappingsFieldNumber,
- protos::pbzero::Mapping>(iid);
- if (!decoder)
- return base::nullopt;
- return MakeSourceMapping(*decoder);
- }
-
- base::Optional<StackProfileTracker::SourceFrame> GetFrame(
- StackProfileTracker::SourceFrameId iid) const override {
- auto* decoder = seq_state_->LookupInternedMessage<
- protos::pbzero::InternedData::kFramesFieldNumber,
- protos::pbzero::Frame>(iid);
- if (!decoder)
- return base::nullopt;
- return MakeSourceFrame(*decoder);
- }
-
- base::Optional<StackProfileTracker::SourceCallstack> GetCallstack(
- StackProfileTracker::SourceCallstackId iid) const override {
- auto* decoder = seq_state_->LookupInternedMessage<
- protos::pbzero::InternedData::kCallstacksFieldNumber,
- protos::pbzero::Callstack>(iid);
- if (!decoder)
- return base::nullopt;
- return MakeSourceCallstack(*decoder);
- }
-
- private:
- PacketSequenceStateGeneration* seq_state_;
-};
-
-} // namespace
-
ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
: context_(context),
metatrace_id_(context->storage->InternString("metatrace")),
@@ -224,9 +127,8 @@ void ProtoTraceParser::ParseTracePacketImpl(
packet.profile_packet());
}
- if (packet.has_streaming_profile_packet()) {
- ParseStreamingProfilePacket(data->sequence_state,
- packet.streaming_profile_packet());
+ if (packet.has_perf_sample()) {
+ ParsePerfSample(ts, data->sequence_state, packet.perf_sample());
}
if (packet.has_chrome_benchmark_metadata()) {
@@ -248,6 +150,18 @@ void ProtoTraceParser::ParseTracePacketImpl(
if (packet.has_module_symbols()) {
ParseModuleSymbols(packet.module_symbols());
}
+
+ if (packet.has_trigger()) {
+ ParseTrigger(ts, packet.trigger());
+ }
+
+ if (packet.has_service_event()) {
+ ParseServiceEvent(ts, packet.service_event());
+ }
+
+ if (packet.has_smaps_packet()) {
+ ParseSmapsPacket(ts, packet.smaps_packet());
+ }
}
void ProtoTraceParser::ParseFtracePacket(uint32_t cpu,
@@ -346,14 +260,16 @@ void ProtoTraceParser::ParseProfilePacket(
for (auto it = packet.mappings(); it; ++it) {
protos::pbzero::Mapping::Decoder entry(*it);
- StackProfileTracker::SourceMapping src_mapping = MakeSourceMapping(entry);
+ StackProfileTracker::SourceMapping src_mapping =
+ ProfilePacketUtils::MakeSourceMapping(entry);
sequence_state->state()->stack_profile_tracker().AddMapping(entry.iid(),
src_mapping);
}
for (auto it = packet.frames(); it; ++it) {
protos::pbzero::Frame::Decoder entry(*it);
- StackProfileTracker::SourceFrame src_frame = MakeSourceFrame(entry);
+ StackProfileTracker::SourceFrame src_frame =
+ ProfilePacketUtils::MakeSourceFrame(entry);
sequence_state->state()->stack_profile_tracker().AddFrame(entry.iid(),
src_frame);
}
@@ -361,7 +277,7 @@ void ProtoTraceParser::ParseProfilePacket(
for (auto it = packet.callstacks(); it; ++it) {
protos::pbzero::Callstack::Decoder entry(*it);
StackProfileTracker::SourceCallstack src_callstack =
- MakeSourceCallstack(entry);
+ ProfilePacketUtils::MakeSourceCallstack(entry);
sequence_state->state()->stack_profile_tracker().AddCallstack(
entry.iid(), src_callstack);
}
@@ -382,6 +298,9 @@ void ProtoTraceParser::ParseProfilePacket(
int pid = static_cast<int>(entry.pid());
+ if (entry.disconnected())
+ context_->storage->IncrementIndexedStats(
+ stats::heapprofd_client_disconnected, pid);
if (entry.buffer_corrupted())
context_->storage->IncrementIndexedStats(
stats::heapprofd_buffer_corrupted, pid);
@@ -391,6 +310,9 @@ void ProtoTraceParser::ParseProfilePacket(
if (entry.rejected_concurrent())
context_->storage->IncrementIndexedStats(
stats::heapprofd_rejected_concurrent, pid);
+ if (entry.hit_guardrail())
+ context_->storage->IncrementIndexedStats(stats::heapprofd_hit_guardrail,
+ pid);
for (auto sample_it = entry.samples(); sample_it; ++sample_it) {
protos::pbzero::ProfilePacket::HeapSample::Decoder sample(*sample_it);
@@ -420,47 +342,55 @@ void ProtoTraceParser::ParseProfilePacket(
}
}
-void ProtoTraceParser::ParseStreamingProfilePacket(
+void ProtoTraceParser::ParsePerfSample(
+ int64_t ts,
PacketSequenceStateGeneration* sequence_state,
ConstBytes blob) {
- protos::pbzero::StreamingProfilePacket::Decoder packet(blob.data, blob.size);
+ using PerfSample = protos::pbzero::PerfSample;
+ PerfSample::Decoder sample(blob.data, blob.size);
- ProcessTracker* procs = context_->process_tracker.get();
- TraceStorage* storage = context_->storage.get();
- StackProfileTracker& stack_profile_tracker =
- sequence_state->state()->stack_profile_tracker();
- ProfilePacketInternLookup intern_lookup(sequence_state);
+ // Not a sample, but an indication of data loss in the ring buffer shared with
+ // the kernel.
+ if (sample.kernel_records_lost() > 0) {
+ PERFETTO_DCHECK(sample.pid() == 0);
- uint32_t pid = static_cast<uint32_t>(sequence_state->state()->pid());
- uint32_t tid = static_cast<uint32_t>(sequence_state->state()->tid());
- UniqueTid utid = procs->UpdateThread(tid, pid);
-
- auto timestamp_it = packet.timestamp_delta_us();
- for (auto callstack_it = packet.callstack_iid(); callstack_it;
- ++callstack_it, ++timestamp_it) {
- if (!timestamp_it) {
- context_->storage->IncrementStats(stats::stackprofile_parser_error);
- PERFETTO_ELOG(
- "StreamingProfilePacket has less callstack IDs than timestamps!");
- break;
- }
+ context_->storage->IncrementIndexedStats(
+ stats::perf_cpu_lost_records, static_cast<int>(sample.cpu()),
+ static_cast<int64_t>(sample.kernel_records_lost()));
+ return;
+ }
- auto maybe_callstack_id = stack_profile_tracker.FindOrInsertCallstack(
- *callstack_it, &intern_lookup);
- if (!maybe_callstack_id) {
- context_->storage->IncrementStats(stats::stackprofile_parser_error);
- PERFETTO_ELOG("StreamingProfilePacket referencing invalid callstack!");
- continue;
- }
+ // Sample that looked relevant for the tracing session, but had to be skipped.
+ // Either we failed to look up the procfs file descriptors necessary for
+ // remote stack unwinding (not unexpected in most cases), or the unwind queue
+ // was out of capacity (producer lost data on its own).
+ if (sample.has_sample_skipped_reason()) {
+ context_->storage->IncrementStats(stats::perf_samples_skipped);
- uint32_t callstack_id = maybe_callstack_id->value;
+ if (sample.sample_skipped_reason() ==
+ PerfSample::PROFILER_SKIP_UNWIND_ENQUEUE)
+ context_->storage->IncrementStats(stats::perf_samples_skipped_dataloss);
+
+ return;
+ }
+
+ uint64_t callstack_iid = sample.callstack_iid();
+ StackProfileTracker& stack_tracker =
+ sequence_state->state()->stack_profile_tracker();
+ ProfilePacketInternLookup intern_lookup(sequence_state);
- tables::CpuProfileStackSampleTable::Row sample_row{
- sequence_state->state()->IncrementAndGetTrackEventTimeNs(*timestamp_it *
- 1000),
- callstack_id, utid};
- storage->mutable_cpu_profile_stack_sample_table()->Insert(sample_row);
+ base::Optional<CallsiteId> cs_id =
+ stack_tracker.FindOrInsertCallstack(callstack_iid, &intern_lookup);
+ if (!cs_id) {
+ context_->storage->IncrementStats(stats::stackprofile_parser_error);
+ PERFETTO_ELOG("PerfSample referencing invalid callstack iid [%" PRIu64
+ "] at timestamp [%" PRIi64 "]",
+ callstack_iid, ts);
+ return;
}
+
+ context_->perf_sample_tracker->AddStackToSliceTrack(
+ ts, *cs_id, sample.pid(), sample.tid(), sample.cpu());
}
void ProtoTraceParser::ParseChromeBenchmarkMetadata(ConstBytes blob) {
@@ -517,8 +447,9 @@ void ProtoTraceParser::ParseChromeEvents(int64_t ts, ConstBytes blob) {
protos::pbzero::ChromeEventBundle::Decoder bundle(blob.data, blob.size);
ArgsTracker args(context_);
if (bundle.has_metadata()) {
- RawId id = storage->mutable_raw_table()->Insert(
- {ts, raw_chrome_metadata_event_id_, 0, 0});
+ RawId id = storage->mutable_raw_table()
+ ->Insert({ts, raw_chrome_metadata_event_id_, 0, 0})
+ .id;
auto inserter = args.AddArgsTo(id);
// Metadata is proxied via a special event in the raw table to JSON export.
@@ -544,8 +475,10 @@ void ProtoTraceParser::ParseChromeEvents(int64_t ts, ConstBytes blob) {
}
if (bundle.has_legacy_ftrace_output()) {
- RawId id = storage->mutable_raw_table()->Insert(
- {ts, raw_chrome_legacy_system_trace_event_id_, 0, 0});
+ RawId id =
+ storage->mutable_raw_table()
+ ->Insert({ts, raw_chrome_legacy_system_trace_event_id_, 0, 0})
+ .id;
std::string data;
for (auto it = bundle.legacy_ftrace_output(); it; ++it) {
@@ -563,8 +496,10 @@ void ProtoTraceParser::ParseChromeEvents(int64_t ts, ConstBytes blob) {
protos::pbzero::ChromeLegacyJsonTrace::USER_TRACE) {
continue;
}
- RawId id = storage->mutable_raw_table()->Insert(
- {ts, raw_chrome_legacy_user_trace_event_id_, 0, 0});
+ RawId id =
+ storage->mutable_raw_table()
+ ->Insert({ts, raw_chrome_legacy_user_trace_event_id_, 0, 0})
+ .id;
Variadic value =
Variadic::String(storage->InternString(legacy_trace.data()));
args.AddArgsTo(id).AddArg(data_name_id_, value);
@@ -629,11 +564,18 @@ void ProtoTraceParser::ParseTraceConfig(ConstBytes blob) {
void ProtoTraceParser::ParseModuleSymbols(ConstBytes blob) {
protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
- std::string hex_build_id = base::ToHex(module_symbols.build_id().data,
- module_symbols.build_id().size);
+ StringId build_id;
+ // TODO(b/148109467): Remove workaround once all active Chrome versions
+ // write raw bytes instead of a string as build_id.
+ if (module_symbols.build_id().size == 33) {
+ build_id = context_->storage->InternString(module_symbols.build_id());
+ } else {
+ build_id = context_->storage->InternString(base::StringView(base::ToHex(
+ module_symbols.build_id().data, module_symbols.build_id().size)));
+ }
+
auto mapping_ids = context_->storage->FindMappingRow(
- context_->storage->InternString(module_symbols.path()),
- context_->storage->InternString(base::StringView(hex_build_id)));
+ context_->storage->InternString(module_symbols.path()), build_id);
if (mapping_ids.empty()) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
return;
@@ -670,5 +612,48 @@ void ProtoTraceParser::ParseModuleSymbols(ConstBytes blob) {
}
}
+void ProtoTraceParser::ParseTrigger(int64_t ts, ConstBytes blob) {
+ protos::pbzero::Trigger::Decoder trigger(blob.data, blob.size);
+ StringId cat_id = kNullStringId;
+ TrackId track_id = context_->track_tracker->GetOrCreateTriggerTrack();
+ StringId name_id = context_->storage->InternString(trigger.trigger_name());
+ context_->slice_tracker->Scoped(
+ ts, track_id, cat_id, name_id,
+ /* duration = */ 0,
+ [&trigger, this](ArgsTracker::BoundInserter* args_table) {
+ StringId producer_name_key =
+ context_->storage->InternString("producer_name");
+ args_table->AddArg(producer_name_key,
+ Variadic::String(context_->storage->InternString(
+ trigger.producer_name())));
+ StringId trusted_producer_uid_key =
+ context_->storage->InternString("trusted_producer_uid");
+ args_table->AddArg(trusted_producer_uid_key,
+ Variadic::Integer(trigger.trusted_producer_uid()));
+ });
+}
+
+void ProtoTraceParser::ParseServiceEvent(int64_t ts, ConstBytes blob) {
+ protos::pbzero::TracingServiceEvent::Decoder tse(blob.data, blob.size);
+ if (tse.all_data_sources_started()) {
+ context_->metadata_tracker->SetMetadata(
+ metadata::all_data_source_started_ns, Variadic::Integer(ts));
+ }
+}
+
+void ProtoTraceParser::ParseSmapsPacket(int64_t ts, ConstBytes blob) {
+ protos::pbzero::SmapsPacket::Decoder sp(blob.data, blob.size);
+ auto upid = context_->process_tracker->GetOrCreateProcess(sp.pid());
+
+ for (auto it = sp.entries(); it; ++it) {
+ protos::pbzero::SmapsEntry::Decoder e(*it);
+ context_->storage->mutable_profiler_smaps_table()->Insert(
+ {upid, ts, context_->storage->InternString(e.path()),
+ static_cast<int64_t>(e.size_kb()),
+ static_cast<int64_t>(e.private_dirty_kb()),
+ static_cast<int64_t>(e.swap_kb())});
+ }
+}
+
} // namespace trace_processor
} // namespace perfetto