[tp] Detect missing processes in Chromium traces
The data is exposed in a new experimental_missing_process_data SQL table.
Bug: b/244285392
Change-Id: I200d75cb3d48d96471eb3078b113e7efba058df6
diff --git a/Android.bp b/Android.bp
index 4f8a3c6..3771992 100644
--- a/Android.bp
+++ b/Android.bp
@@ -9125,6 +9125,7 @@
filegroup {
name: "perfetto_src_trace_processor_importers_proto_storage_minimal",
srcs: [
+ "src/trace_processor/importers/proto/active_chrome_processes_tracker.cc",
"src/trace_processor/importers/proto/heap_profile_tracker.cc",
"src/trace_processor/importers/proto/profiler_util.cc",
"src/trace_processor/importers/proto/stack_profile_tracker.cc",
@@ -9135,6 +9136,7 @@
filegroup {
name: "perfetto_src_trace_processor_importers_proto_unittests",
srcs: [
+ "src/trace_processor/importers/proto/active_chrome_processes_tracker_unittest.cc",
"src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc",
"src/trace_processor/importers/proto/heap_profile_tracker_unittest.cc",
],
diff --git a/BUILD b/BUILD
index ab137e9..9c7ccec 100644
--- a/BUILD
+++ b/BUILD
@@ -1152,6 +1152,8 @@
perfetto_filegroup(
name = "src_trace_processor_importers_proto_storage_minimal",
srcs = [
+ "src/trace_processor/importers/proto/active_chrome_processes_tracker.cc",
+ "src/trace_processor/importers/proto/active_chrome_processes_tracker.h",
"src/trace_processor/importers/proto/heap_profile_tracker.cc",
"src/trace_processor/importers/proto/heap_profile_tracker.h",
"src/trace_processor/importers/proto/profiler_util.cc",
diff --git a/src/trace_processor/importers/proto/BUILD.gn b/src/trace_processor/importers/proto/BUILD.gn
index 732e002..48c2f26 100644
--- a/src/trace_processor/importers/proto/BUILD.gn
+++ b/src/trace_processor/importers/proto/BUILD.gn
@@ -14,6 +14,8 @@
source_set("storage_minimal") {
sources = [
+ "active_chrome_processes_tracker.cc",
+ "active_chrome_processes_tracker.h",
"heap_profile_tracker.cc",
"heap_profile_tracker.h",
"profiler_util.cc",
@@ -53,6 +55,7 @@
source_set("unittests") {
testonly = true
sources = [
+ "active_chrome_processes_tracker_unittest.cc",
"heap_graph_tracker_unittest.cc",
"heap_profile_tracker_unittest.cc",
]
diff --git a/src/trace_processor/importers/proto/active_chrome_processes_tracker.cc b/src/trace_processor/importers/proto/active_chrome_processes_tracker.cc
new file mode 100644
index 0000000..4a54095
--- /dev/null
+++ b/src/trace_processor/importers/proto/active_chrome_processes_tracker.cc
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/importers/proto/active_chrome_processes_tracker.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+std::vector<ProcessWithDataLoss>
+ActiveChromeProcessesTracker::GetProcessesWithDataLoss() const {
+ std::vector<ProcessWithDataLoss> processes_with_data_loss;
+ for (auto it = process_data_.GetIterator(); it; ++it) {
+ UniquePid upid = it.key();
+ const auto& process_data = it.value();
+ base::Optional<int64_t> last_loss_moment;
+ base::Optional<int64_t> next_no_loss_moment;
+ for (int64_t metadata_ts : process_data.metadata_timestamps) {
+ // Looks for a matching process descriptor in the [t - 0.2s, t + 0.2s]
+ // window. The window size is somewhat arbitrary, and can be changed in
+ // the future. It should be smaller than the incremental state reset
+ // interval, which is 5s for Chromium traces.
+ constexpr int64_t kMaxTimestampDiff = 200 * 1000 * 1000;
+ auto descriptor_it = process_data.descriptor_timestamps.lower_bound(
+ metadata_ts - kMaxTimestampDiff);
+ if (descriptor_it != process_data.descriptor_timestamps.end()) {
+ if (*descriptor_it > metadata_ts + kMaxTimestampDiff) {
+ // There's no matching descriptor, but there's a descriptor at some
+ // point in the future.
+ last_loss_moment = metadata_ts;
+ next_no_loss_moment = *descriptor_it;
+ }
+ } else {
+ // There's no matching descriptor, and there're no descriptors in the
+ // future.
+ last_loss_moment = metadata_ts;
+ next_no_loss_moment = base::nullopt;
+ break;
+ }
+ }
+ if (last_loss_moment) {
+ processes_with_data_loss.push_back({upid, next_no_loss_moment});
+ }
+ }
+ return processes_with_data_loss;
+}
+
+void ActiveChromeProcessesTracker::NotifyEndOfFile() {
+ const auto processes = GetProcessesWithDataLoss();
+ for (const auto& p : processes) {
+ tables::ExperimentalMissingChromeProcessesTable::Row row;
+ row.upid = p.upid;
+ row.reliable_from = p.reliable_from;
+ context_->storage->mutable_experimental_missing_chrome_processes_table()
+ ->Insert(row);
+ }
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/active_chrome_processes_tracker.h b/src/trace_processor/importers/proto/active_chrome_processes_tracker.h
new file mode 100644
index 0000000..ed5b83d
--- /dev/null
+++ b/src/trace_processor/importers/proto/active_chrome_processes_tracker.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ACTIVE_CHROME_PROCESSES_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ACTIVE_CHROME_PROCESSES_TRACKER_H_
+
+#include <set>
+#include <vector>
+#include "perfetto/ext/base/optional.h"
+
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+struct ProcessWithDataLoss {
+ UniquePid upid;
+ // If not nullopt, the process data is reliable from this point until
+ // the end of the trace.
+ base::Optional<int64_t> reliable_from;
+};
+
+// Tracks ActiveProcesses metadata packets from ChromeTrackEvent,
+// and process descriptors.
+// Computes a list of processes with missing data based on this information.
+class ActiveChromeProcessesTracker {
+ public:
+ explicit ActiveChromeProcessesTracker(TraceProcessorContext* context)
+ : context_(context) {}
+
+ void AddActiveProcessMetadata(int64_t timestamp, UniquePid upid) {
+ process_data_[upid].metadata_timestamps.insert(timestamp);
+ }
+ void AddProcessDescriptor(int64_t timestamp, UniquePid upid) {
+ process_data_[upid].descriptor_timestamps.insert(timestamp);
+ }
+ std::vector<ProcessWithDataLoss> GetProcessesWithDataLoss() const;
+ void NotifyEndOfFile();
+
+ private:
+ struct ProcessData {
+ std::set<int64_t> metadata_timestamps;
+ std::set<int64_t> descriptor_timestamps;
+ };
+
+ TraceProcessorContext* context_;
+ base::FlatHashMap<UniquePid, ProcessData> process_data_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ACTIVE_CHROME_PROCESSES_TRACKER_H_
diff --git a/src/trace_processor/importers/proto/active_chrome_processes_tracker_unittest.cc b/src/trace_processor/importers/proto/active_chrome_processes_tracker_unittest.cc
new file mode 100644
index 0000000..6fdc1e8
--- /dev/null
+++ b/src/trace_processor/importers/proto/active_chrome_processes_tracker_unittest.cc
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/importers/proto/active_chrome_processes_tracker.h"
+
+#include "perfetto/base/logging.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+static bool operator==(const ProcessWithDataLoss& lhs,
+ const ProcessWithDataLoss& rhs) {
+ return lhs.upid == rhs.upid && lhs.reliable_from == rhs.reliable_from;
+}
+
+namespace {
+
+using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAre;
+
+constexpr int64_t kNanosecondsInSecond = 1000 * 1000 * 1000;
+
+TEST(ActiveChromeProcessesTrackerTest, NoMetadataAndNoDescriptors) {
+ // No metadata and no descriptor = no processes are missing.
+ ActiveChromeProcessesTracker tracker(nullptr);
+ EXPECT_THAT(tracker.GetProcessesWithDataLoss(), IsEmpty());
+}
+
+TEST(ActiveChromeProcessesTrackerTest, NoDescriptors) {
+ ActiveChromeProcessesTracker tracker(nullptr);
+ tracker.AddActiveProcessMetadata(/*timestamp=*/10, /*upid=*/1);
+ tracker.AddActiveProcessMetadata(/*timestamp=*/10, /*upid=*/2);
+ EXPECT_THAT(tracker.GetProcessesWithDataLoss(),
+ UnorderedElementsAre(ProcessWithDataLoss{1, base::nullopt},
+ ProcessWithDataLoss{2, base::nullopt}));
+}
+
+TEST(ActiveChromeProcessesTrackerTest, InexactMatch) {
+ ActiveChromeProcessesTracker tracker(nullptr);
+ tracker.AddActiveProcessMetadata(/*timestamp=*/10 * kNanosecondsInSecond,
+ /*upid=*/1);
+ tracker.AddActiveProcessMetadata(/*timestamp=*/15 * kNanosecondsInSecond,
+ /*upid=*/1);
+ tracker.AddProcessDescriptor(
+ /*timestamp=*/10 * kNanosecondsInSecond - 200 * 1000 * 1000, /*upid=*/1);
+ tracker.AddProcessDescriptor(
+ /*timestamp=*/15 * kNanosecondsInSecond + 200 * 1000 * 1000, /*upid=*/1);
+ EXPECT_THAT(tracker.GetProcessesWithDataLoss(), IsEmpty());
+}
+
+TEST(ActiveChromeProcessesTrackerTest, InexactMatchTooBigDiff) {
+ ActiveChromeProcessesTracker tracker(nullptr);
+ tracker.AddActiveProcessMetadata(/*timestamp=*/10 * kNanosecondsInSecond,
+ /*upid=*/1);
+ tracker.AddActiveProcessMetadata(/*timestamp=*/15 * kNanosecondsInSecond,
+ /*upid=*/1);
+ tracker.AddProcessDescriptor(
+ /*timestamp=*/10 * kNanosecondsInSecond - 200 * 1000 * 1000 - 1,
+ /*upid=*/1);
+ tracker.AddProcessDescriptor(
+ /*timestamp=*/15 * kNanosecondsInSecond + 200 * 1000 * 1000 + 1,
+ /*upid=*/1);
+ EXPECT_THAT(tracker.GetProcessesWithDataLoss(),
+ UnorderedElementsAre(ProcessWithDataLoss{
+ 1, 15 * kNanosecondsInSecond + 200 * 1000 * 1000 + 1}));
+}
+
+TEST(ActiveChromeProcessesTrackerTest, ExtraDescriptor) {
+ // There're more descriptors than metadata packets - this is OK.
+ ActiveChromeProcessesTracker tracker(nullptr);
+ tracker.AddActiveProcessMetadata(/*timestamp=*/15 * kNanosecondsInSecond,
+ /*upid=*/1);
+ tracker.AddProcessDescriptor(/*timestamp=*/10 * kNanosecondsInSecond,
+ /*upid=*/1);
+ tracker.AddProcessDescriptor(/*timestamp=*/15 * kNanosecondsInSecond,
+ /*upid=*/1);
+ EXPECT_THAT(tracker.GetProcessesWithDataLoss(), IsEmpty());
+}
+
+} // namespace
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_module.cc b/src/trace_processor/importers/proto/track_event_module.cc
index f0ece26..547bf3b 100644
--- a/src/trace_processor/importers/proto/track_event_module.cc
+++ b/src/trace_processor/importers/proto/track_event_module.cc
@@ -72,17 +72,17 @@
}
void TrackEventModule::ParseTracePacketData(const TracePacket::Decoder& decoder,
- int64_t,
+ int64_t ts,
const TracePacketData&,
uint32_t field_id) {
switch (field_id) {
case TracePacket::kTrackDescriptorFieldNumber:
- parser_.ParseTrackDescriptor(decoder.track_descriptor(),
+ parser_.ParseTrackDescriptor(ts, decoder.track_descriptor(),
decoder.trusted_packet_sequence_id());
break;
case TracePacket::kProcessDescriptorFieldNumber:
// TODO(eseckler): Remove once Chrome has switched to TrackDescriptors.
- parser_.ParseProcessDescriptor(decoder.process_descriptor());
+ parser_.ParseProcessDescriptor(ts, decoder.process_descriptor());
break;
case TracePacket::kThreadDescriptorFieldNumber:
// TODO(eseckler): Remove once Chrome has switched to TrackDescriptors.
@@ -101,5 +101,9 @@
track_event_tracker_->OnFirstPacketOnSequence(packet_sequence_id);
}
+void TrackEventModule::NotifyEndOfFile() {
+ parser_.NotifyEndOfFile();
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_module.h b/src/trace_processor/importers/proto/track_event_module.h
index 54652a1..2b68a88 100644
--- a/src/trace_processor/importers/proto/track_event_module.h
+++ b/src/trace_processor/importers/proto/track_event_module.h
@@ -52,6 +52,8 @@
const TracePacketData& data,
uint32_t field_id) override;
+ void NotifyEndOfFile() override;
+
private:
std::unique_ptr<TrackEventTracker> track_event_tracker_;
TrackEventTokenizer tokenizer_;
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index bf6041f..cd8f7a5 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -70,10 +70,12 @@
class TrackEventArgsParser : public util::ProtoToArgsParser::Delegate {
public:
- TrackEventArgsParser(BoundInserter& inserter,
+ TrackEventArgsParser(int64_t packet_timestamp,
+ BoundInserter& inserter,
TraceStorage& storage,
PacketSequenceStateGeneration& sequence_state)
- : inserter_(inserter),
+ : packet_timestamp_(packet_timestamp),
+ inserter_(inserter),
storage_(storage),
sequence_state_(sequence_state) {}
@@ -146,9 +148,12 @@
return sequence_state_.GetInternedMessageView(field_id, iid);
}
+ int64_t packet_timestamp() final { return packet_timestamp_; }
+
PacketSequenceStateGeneration* seq_state() final { return &sequence_state_; }
private:
+ int64_t packet_timestamp_;
BoundInserter& inserter_;
TraceStorage& storage_;
PacketSequenceStateGeneration& sequence_state_;
@@ -1177,7 +1182,8 @@
ParseHistogramName(event_.chrome_histogram_sample(), inserter));
}
- TrackEventArgsParser args_writer(*inserter, *storage_, *sequence_state_);
+ TrackEventArgsParser args_writer(ts_, *inserter, *storage_,
+ *sequence_state_);
int unknown_extensions = 0;
log_errors(parser_->args_parser_.ParseMessage(
blob_, ".perfetto.protos.TrackEvent", &parser_->reflect_fields_,
@@ -1466,7 +1472,8 @@
chrome_string_lookup_(context->storage.get()),
counter_unit_ids_{{kNullStringId, context_->storage->InternString("ns"),
context_->storage->InternString("count"),
- context_->storage->InternString("bytes")}} {
+ context_->storage->InternString("bytes")}},
+ active_chrome_processes_tracker_(context) {
args_parser_.AddParsingOverrideForField(
"chrome_mojo_event_info.mojo_interface_method_iid",
[](const protozero::Field& field,
@@ -1518,12 +1525,24 @@
return annotation_parser.Parse(data, delegate);
});
+ args_parser_.AddParsingOverrideForField(
+ "active_processes.pid", [&](const protozero::Field& field,
+ util::ProtoToArgsParser::Delegate& delegate) {
+ UniquePid upid = context_->process_tracker->GetOrCreateProcess(
+ static_cast<uint32_t>(field.as_int32()));
+ active_chrome_processes_tracker_.AddActiveProcessMetadata(
+ delegate.packet_timestamp(), upid);
+ // Fallthrough so that the parser adds pid as a regular arg.
+ return base::nullopt;
+ });
+
for (uint16_t index : kReflectFields) {
reflect_fields_.push_back(index);
}
}
void TrackEventParser::ParseTrackDescriptor(
+ int64_t packet_timestamp,
protozero::ConstBytes track_descriptor,
uint32_t packet_sequence_id) {
protos::pbzero::TrackDescriptor::Decoder decoder(track_descriptor);
@@ -1538,7 +1557,8 @@
if (decoder.has_chrome_thread())
ParseChromeThreadDescriptor(utid, decoder.chrome_thread());
} else if (decoder.has_process()) {
- UniquePid upid = ParseProcessDescriptor(decoder.process());
+ UniquePid upid =
+ ParseProcessDescriptor(packet_timestamp, decoder.process());
if (decoder.has_chrome_process())
ParseChromeProcessDescriptor(upid, decoder.chrome_process());
} else if (decoder.has_counter()) {
@@ -1554,10 +1574,12 @@
}
UniquePid TrackEventParser::ParseProcessDescriptor(
+ int64_t packet_timestamp,
protozero::ConstBytes process_descriptor) {
protos::pbzero::ProcessDescriptor::Decoder decoder(process_descriptor);
UniquePid upid = context_->process_tracker->GetOrCreateProcess(
static_cast<uint32_t>(decoder.pid()));
+ active_chrome_processes_tracker_.AddProcessDescriptor(packet_timestamp, upid);
if (decoder.has_process_name() && decoder.process_name().size) {
// Don't override system-provided names.
context_->process_tracker->SetProcessNameIfUnset(
@@ -1696,5 +1718,9 @@
}
}
+void TrackEventParser::NotifyEndOfFile() {
+ active_chrome_processes_tracker_.NotifyEndOfFile();
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
index 6033b2c..72b3bf3 100644
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ b/src/trace_processor/importers/proto/track_event_parser.h
@@ -25,6 +25,7 @@
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/trace_parser.h"
+#include "src/trace_processor/importers/proto/active_chrome_processes_tracker.h"
#include "src/trace_processor/importers/proto/chrome_string_lookup.h"
#include "src/trace_processor/parser_types.h"
#include "src/trace_processor/storage/trace_storage.h"
@@ -54,8 +55,11 @@
public:
TrackEventParser(TraceProcessorContext*, TrackEventTracker*);
- void ParseTrackDescriptor(protozero::ConstBytes, uint32_t packet_sequence_id);
- UniquePid ParseProcessDescriptor(protozero::ConstBytes);
+ void ParseTrackDescriptor(int64_t packet_timestamp,
+ protozero::ConstBytes,
+ uint32_t packet_sequence_id);
+ UniquePid ParseProcessDescriptor(int64_t packet_timestamp,
+ protozero::ConstBytes);
UniqueTid ParseThreadDescriptor(protozero::ConstBytes);
void ParseTrackEvent(int64_t ts,
@@ -63,6 +67,8 @@
protozero::ConstBytes,
uint32_t packet_sequence_id);
+ void NotifyEndOfFile();
+
private:
class EventImporter;
@@ -121,6 +127,8 @@
std::array<StringId, 4> counter_unit_ids_;
std::vector<uint16_t> reflect_fields_;
+
+ ActiveChromeProcessesTracker active_chrome_processes_tracker_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index 8fd886f..6b85fed 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -694,6 +694,15 @@
return &experimental_proto_content_table_;
}
+ const tables::ExperimentalMissingChromeProcessesTable&
+ experimental_missing_chrome_processes_table() const {
+ return experimental_missing_chrome_processes_table_;
+ }
+ tables::ExperimentalMissingChromeProcessesTable*
+ mutable_experimental_missing_chrome_processes_table() {
+ return &experimental_missing_chrome_processes_table_;
+ }
+
const views::ThreadSliceView& thread_slice_view() const {
return thread_slice_view_;
}
@@ -927,6 +936,9 @@
tables::ExperimentalProtoContentTable experimental_proto_content_table_{
&string_pool_, nullptr};
+ tables::ExperimentalMissingChromeProcessesTable
+ experimental_missing_chrome_processes_table_{&string_pool_, nullptr};
+
views::ThreadSliceView thread_slice_view_{&slice_table_, &thread_track_table_,
&thread_table_};
diff --git a/src/trace_processor/tables/metadata_tables.h b/src/trace_processor/tables/metadata_tables.h
index 2654ee4..562dd84 100644
--- a/src/trace_processor/tables/metadata_tables.h
+++ b/src/trace_processor/tables/metadata_tables.h
@@ -140,6 +140,17 @@
PERFETTO_TP_TABLE(PERFETTO_TP_PROCESS_TABLE_DEF);
+// Experimental table, subject to arbitrary breaking changes.
+#define PERFETTO_TP_EXPERIMENTAL_MISSING_CHROME_PROCESSES_TABLE_DEF(NAME, \
+ PARENT, C) \
+ NAME(ExperimentalMissingChromeProcessesTable, \
+ "experimental_missing_chrome_processes") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(uint32_t, upid) \
+ C(base::Optional<int64_t>, reliable_from)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_EXPERIMENTAL_MISSING_CHROME_PROCESSES_TABLE_DEF);
+
// Contains information of processes seen during the trace
//
// @name cpu
diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc
index 8ee86fa..115a89e 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -43,6 +43,8 @@
// metadata_tables.h
RawTable::~RawTable() = default;
ArgTable::~ArgTable() = default;
+ExperimentalMissingChromeProcessesTable::
+ ~ExperimentalMissingChromeProcessesTable() = default;
MetadataTable::~MetadataTable() = default;
CpuTable::~CpuTable() = default;
CpuFreqTable::~CpuFreqTable() = default;
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 9be69b7..3bbe937 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -1136,6 +1136,8 @@
RegisterDbTable(storage->memory_snapshot_edge_table());
RegisterDbTable(storage->experimental_proto_content_table());
+
+ RegisterDbTable(storage->experimental_missing_chrome_processes_table());
}
TraceProcessorImpl::~TraceProcessorImpl() = default;
diff --git a/src/trace_processor/util/proto_to_args_parser.h b/src/trace_processor/util/proto_to_args_parser.h
index 86fbcd1..5e54775 100644
--- a/src/trace_processor/util/proto_to_args_parser.h
+++ b/src/trace_processor/util/proto_to_args_parser.h
@@ -95,6 +95,8 @@
virtual PacketSequenceStateGeneration* seq_state() = 0;
+ virtual int64_t packet_timestamp() { return 0; }
+
template <typename FieldMetadata>
typename FieldMetadata::cpp_field_type::Decoder* GetInternedMessage(
protozero::proto_utils::internal::FieldMetadataHelper<FieldMetadata>,
diff --git a/test/trace_processor/chrome/chrome_missing_processes.out b/test/trace_processor/chrome/chrome_missing_processes.out
new file mode 100644
index 0000000..d3583ae
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_missing_processes.out
@@ -0,0 +1,3 @@
+"upid","pid","reliable_from"
+2,100,1000000000
+3,1000,"[NULL]"
diff --git a/test/trace_processor/chrome/chrome_missing_processes.textproto b/test/trace_processor/chrome/chrome_missing_processes.textproto
new file mode 100644
index 0000000..5f62e09
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_missing_processes.textproto
@@ -0,0 +1,36 @@
+packet {
+ timestamp: 1
+ incremental_state_cleared: true
+ trusted_packet_sequence_id: 1
+ track_event {
+ type: TYPE_INSTANT
+ name: "ActiveProcesses"
+ [perfetto.protos.ChromeTrackEvent.active_processes]: {
+ pid: 10
+ pid: 100
+ pid: 1000
+ }
+ }
+}
+packet {
+ timestamp: 1
+ trusted_packet_sequence_id: 2
+ track_descriptor {
+ uuid: 1
+ process {
+ pid: 10
+ }
+ parent_uuid: 0
+ }
+}
+packet {
+ timestamp: 1000000000
+ trusted_packet_sequence_id: 3
+ track_descriptor {
+ uuid: 2
+ process {
+ pid: 100
+ }
+ parent_uuid: 0
+ }
+}
\ No newline at end of file
diff --git a/test/trace_processor/chrome/chrome_missing_processes_args.out b/test/trace_processor/chrome/chrome_missing_processes_args.out
new file mode 100644
index 0000000..acc7c28
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_missing_processes_args.out
@@ -0,0 +1,4 @@
+"arg_set_id","key","int_value"
+2,"active_processes.pid[0]",10
+2,"active_processes.pid[1]",100
+2,"active_processes.pid[2]",1000
diff --git a/test/trace_processor/chrome/chrome_missing_processes_args_test.sql b/test/trace_processor/chrome/chrome_missing_processes_args_test.sql
new file mode 100644
index 0000000..b404cbd
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_missing_processes_args_test.sql
@@ -0,0 +1,22 @@
+--
+-- Copyright 2022 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+SELECT arg_set_id, key, int_value
+FROM
+ slice
+JOIN
+ args
+USING(arg_set_id)
+ORDER BY arg_set_id, key;
\ No newline at end of file
diff --git a/test/trace_processor/chrome/chrome_missing_processes_default_trace.out b/test/trace_processor/chrome/chrome_missing_processes_default_trace.out
new file mode 100644
index 0000000..43e28ea
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_missing_processes_default_trace.out
@@ -0,0 +1 @@
+"upid","pid","reliable_from"
diff --git a/test/trace_processor/chrome/chrome_missing_processes_test.sql b/test/trace_processor/chrome/chrome_missing_processes_test.sql
new file mode 100644
index 0000000..30ef9e5
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_missing_processes_test.sql
@@ -0,0 +1,22 @@
+--
+-- Copyright 2022 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+SELECT upid, pid, reliable_from
+FROM
+ experimental_missing_chrome_processes
+JOIN
+ process
+USING(upid)
+ORDER BY upid;
\ No newline at end of file
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
index 59cc592..18282b2 100644
--- a/test/trace_processor/chrome/index
+++ b/test/trace_processor/chrome/index
@@ -92,3 +92,8 @@
# Log messages.
chrome_log_message.textproto chrome_log_message_test.sql chrome_log_message.out
chrome_log_message.textproto chrome_log_message_args_test.sql chrome_log_message_args.out
+
+# Missing processes.
+../../data/chrome_scroll_without_vsync.pftrace chrome_missing_processes_test.sql chrome_missing_processes_default_trace.out
+chrome_missing_processes.textproto chrome_missing_processes_test.sql chrome_missing_processes.out
+chrome_missing_processes.textproto chrome_missing_processes_args_test.sql chrome_missing_processes_args.out