Merge "Reland "Support packed fields for HeapGraph.""
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 5cd950a..5b5d5b7 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -3049,7 +3049,7 @@
ROOT_JNI_MONITOR = 14;
};
// Objects retained by this root.
- repeated uint64 object_ids = 1;
+ repeated uint64 object_ids = 1 [packed = true];
optional Type root_type = 2;
}
@@ -3065,10 +3065,10 @@
// Indices for InternedData.field_names for the name of the field referring
// to the object.
- repeated uint64 reference_field_id = 4;
+ repeated uint64 reference_field_id = 4 [packed = true];
// Ids of the Object that is referred to.
- repeated uint64 reference_object_id = 5;
+ repeated uint64 reference_object_id = 5 [packed = true];
}
message HeapGraph {
diff --git a/protos/perfetto/trace/profiling/heap_graph.proto b/protos/perfetto/trace/profiling/heap_graph.proto
index d29c292..7e2d5d4 100644
--- a/protos/perfetto/trace/profiling/heap_graph.proto
+++ b/protos/perfetto/trace/profiling/heap_graph.proto
@@ -43,7 +43,7 @@
ROOT_JNI_MONITOR = 14;
};
// Objects retained by this root.
- repeated uint64 object_ids = 1;
+ repeated uint64 object_ids = 1 [packed = true];
optional Type root_type = 2;
}
@@ -59,10 +59,10 @@
// Indices for InternedData.field_names for the name of the field referring
// to the object.
- repeated uint64 reference_field_id = 4;
+ repeated uint64 reference_field_id = 4 [packed = true];
// Ids of the Object that is referred to.
- repeated uint64 reference_object_id = 5;
+ repeated uint64 reference_object_id = 5 [packed = true];
}
message HeapGraph {
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
index 50bba45..7216d90 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -65,6 +65,28 @@
}
}
+// Iterate over a repeated field of varints, independent of whether it is
+// packed or not.
+template <int32_t field_no, typename T, typename F>
+bool ForEachVarInt(const T& decoder, F fn) {
+ auto field = decoder.template at<field_no>();
+ bool parse_error = false;
+ if (field.type() == protozero::proto_utils::ProtoWireType::kLengthDelimited) {
+ // packed repeated
+ auto it = decoder.template GetPackedRepeated<
+ ::protozero::proto_utils::ProtoWireType::kVarInt, uint64_t>(
+ field_no, &parse_error);
+ for (; it; ++it)
+ fn(*it);
+ } else {
+ // non-packed repeated
+ auto it = decoder.template GetRepeated<uint64_t>(field_no);
+ for (; it; ++it)
+ fn(*it);
+ }
+ return parse_error;
+}
+
} // namespace
void HeapGraphModule::ParseHeapGraph(int64_t ts, protozero::ConstBytes blob) {
@@ -78,21 +100,37 @@
obj.object_id = object.id();
obj.self_size = object.self_size();
obj.type_id = object.type_id();
- auto ref_field_ids_it = object.reference_field_id();
- auto ref_object_ids_it = object.reference_object_id();
- for (; ref_field_ids_it && ref_object_ids_it;
- ++ref_field_ids_it, ++ref_object_ids_it) {
- HeapGraphTracker::SourceObject::Reference ref;
- ref.field_name_id = *ref_field_ids_it;
- ref.owned_object_id = *ref_object_ids_it;
- obj.references.emplace_back(std::move(ref));
+
+ std::vector<uint64_t> field_ids;
+ std::vector<uint64_t> object_ids;
+
+ bool parse_error = ForEachVarInt<
+ protos::pbzero::HeapGraphObject::kReferenceFieldIdFieldNumber>(
+ object, [&field_ids](uint64_t value) { field_ids.push_back(value); });
+
+ if (!parse_error) {
+ parse_error = ForEachVarInt<
+ protos::pbzero::HeapGraphObject::kReferenceObjectIdFieldNumber>(
+ object,
+ [&object_ids](uint64_t value) { object_ids.push_back(value); });
}
- if (ref_field_ids_it || ref_object_ids_it) {
- context_->storage->IncrementIndexedStats(stats::heap_graph_missing_packet,
- static_cast<int>(upid));
+ if (parse_error) {
+ context_->storage->IncrementIndexedStats(
+ stats::heap_graph_malformed_packet, static_cast<int>(upid));
+ break;
+ }
+ if (field_ids.size() != object_ids.size()) {
+ context_->storage->IncrementIndexedStats(
+ stats::heap_graph_malformed_packet, static_cast<int>(upid));
continue;
}
+ for (size_t i = 0; i < field_ids.size(); ++i) {
+ HeapGraphTracker::SourceObject::Reference ref;
+ ref.field_name_id = field_ids[i];
+ ref.owned_object_id = object_ids[i];
+ obj.references.emplace_back(std::move(ref));
+ }
context_->heap_graph_tracker->AddObject(upid, ts, std::move(obj));
}
for (auto it = heap_graph.type_names(); it; ++it) {
@@ -118,8 +156,16 @@
HeapGraphTracker::SourceRoot src_root;
src_root.root_type = context_->storage->InternString(str_view);
- for (auto obj_it = entry.object_ids(); obj_it; ++obj_it)
- src_root.object_ids.emplace_back(*obj_it);
+ bool parse_error =
+ ForEachVarInt<protos::pbzero::HeapGraphRoot::kObjectIdsFieldNumber>(
+ entry, [&src_root](uint64_t value) {
+ src_root.object_ids.emplace_back(value);
+ });
+ if (parse_error) {
+ context_->storage->IncrementIndexedStats(
+ stats::heap_graph_malformed_packet, static_cast<int>(upid));
+ break;
+ }
context_->heap_graph_tracker->AddRoot(upid, ts, std::move(src_root));
}
if (!heap_graph.continued()) {