Add new table for heap_graph_class.
Bug: 150546312
Change-Id: I19d1983327882f0f07dc9ca346564535637d9f15
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
index d3974ef..3ca232a 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -229,7 +229,7 @@
PERFETTO_DLOG("Class string %s not found",
cls.obfuscated_name().ToStdString().c_str());
} else {
- const std::vector<int64_t>* cls_objects =
+ const std::vector<tables::HeapGraphClassTable::Id>* cls_objects =
heap_graph_tracker->RowsForType(*obfuscated_class_name_id);
if (cls_objects) {
@@ -237,14 +237,18 @@
*obfuscated_class_name_id,
context_->storage->InternString(
base::StringView(cls.deobfuscated_name())));
- for (int64_t row : *cls_objects) {
+
+ for (tables::HeapGraphClassTable::Id id : *cls_objects) {
+ uint32_t row =
+ *context_->storage->heap_graph_class_table().id().IndexOf(id);
const StringPool::Id obfuscated_type_name =
- context_->storage->mutable_heap_graph_object_table()
- ->type_name()[static_cast<uint32_t>(row)];
- context_->storage->mutable_heap_graph_object_table()
- ->mutable_deobfuscated_type_name()
- ->Set(static_cast<uint32_t>(row),
- heap_graph_tracker->MaybeDeobfuscate(obfuscated_type_name));
+ context_->storage->heap_graph_class_table().name()[row];
+ StringPool::Id deobfuscated_type_name =
+ heap_graph_tracker->MaybeDeobfuscate(obfuscated_type_name);
+ PERFETTO_CHECK(!deobfuscated_type_name.is_null());
+ context_->storage->mutable_heap_graph_class_table()
+ ->mutable_deobfuscated_name()
+ ->Set(row, deobfuscated_type_name);
}
} else {
PERFETTO_DLOG("Class %s not found",
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
index 2a429cd..9b370e2 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -187,31 +187,60 @@
void HeapGraphTracker::FinalizeProfile(uint32_t seq_id) {
SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+
+ std::map<uint64_t, tables::HeapGraphClassTable::Id> type_id_to_db;
+ for (const auto& p : sequence_state.interned_types) {
+ uint64_t id = p.first;
+ const InternedType& interned_type = p.second;
+ base::Optional<StringPool::Id> location_name;
+ if (interned_type.location_id) {
+ auto it = sequence_state.interned_location_names.find(
+ *interned_type.location_id);
+ if (it == sequence_state.interned_location_names.end()) {
+ context_->storage->IncrementIndexedStats(
+ stats::heap_graph_invalid_string_id,
+ static_cast<int>(sequence_state.current_upid));
+
+ } else {
+ location_name = it->second;
+ }
+ }
+ auto id_and_row =
+ context_->storage->mutable_heap_graph_class_table()->Insert(
+ {interned_type.name, base::nullopt, location_name});
+
+ type_id_to_db[id] = id_and_row.id;
+ base::StringView normalized_type =
+ NormalizeTypeName(context_->storage->GetString(interned_type.name));
+ class_to_rows_[context_->storage->InternString(normalized_type)]
+ .emplace_back(id_and_row.id);
+ }
+
for (const SourceObject& obj : sequence_state.current_objects) {
- auto it = sequence_state.interned_types.find(obj.type_id);
- if (it == sequence_state.interned_types.end()) {
+ auto type_it = type_id_to_db.find(obj.type_id);
+ if (type_it == type_id_to_db.end()) {
context_->storage->IncrementIndexedStats(
- stats::heap_graph_invalid_string_id,
+ stats::heap_graph_malformed_packet,
static_cast<int>(sequence_state.current_upid));
continue;
}
- const InternedType& interned_type = it->second;
- StringPool::Id type_name = interned_type.name;
- context_->storage->mutable_heap_graph_object_table()->Insert(
- {sequence_state.current_upid, sequence_state.current_ts,
- static_cast<int64_t>(obj.object_id),
- static_cast<int64_t>(obj.self_size), /*retained_size=*/-1,
- /*unique_retained_size=*/-1, /*reference_set_id=*/base::nullopt,
- /*reachable=*/0, /*type_name=*/type_name,
- /*deobfuscated_type_name=*/base::nullopt,
- /*root_type=*/base::nullopt});
- int64_t row = context_->storage->heap_graph_object_table().row_count() - 1;
+ tables::HeapGraphClassTable::Id db_id = type_it->second;
+ auto id_and_row =
+ context_->storage->mutable_heap_graph_object_table()->Insert(
+ {sequence_state.current_upid, sequence_state.current_ts,
+ static_cast<int64_t>(obj.object_id),
+ static_cast<int64_t>(obj.self_size), /*retained_size=*/-1,
+ /*unique_retained_size=*/-1, /*reference_set_id=*/base::nullopt,
+ /*reachable=*/0, db_id,
+ /*root_type=*/base::nullopt});
+ int64_t row = id_and_row.row;
sequence_state.object_id_to_row.emplace(obj.object_id, row);
- base::StringView normalized_type =
- NormalizeTypeName(context_->storage->GetString(type_name));
- class_to_rows_[context_->storage->InternString(normalized_type)]
- .emplace_back(row);
- sequence_state.walker.AddNode(row, obj.self_size, type_name.raw_id());
+ int64_t type_row =
+ *context_->storage->heap_graph_class_table().id().IndexOf(db_id);
+ // Still using raw rows for the HeapGraphWalker to not tie it to the
+ // data base and make it useable independently.
+ // We will eventually want to use that client-side for summarization.
+ sequence_state.walker.AddNode(row, obj.self_size, type_row);
}
for (const SourceObject& obj : sequence_state.current_objects) {
@@ -323,12 +352,21 @@
parent_id = node_to_id[node.parent_id];
const uint32_t depth = node.depth;
+ base::Optional<StringPool::Id> name =
+ context_->storage->heap_graph_class_table()
+ .deobfuscated_name()[static_cast<uint32_t>(node.class_name)];
+ if (!name) {
+ name = context_->storage->heap_graph_class_table()
+ .name()[static_cast<uint32_t>(node.class_name)];
+ }
+ PERFETTO_CHECK(name);
+
tables::ExperimentalFlamegraphNodesTable::Row alloc_row{};
alloc_row.ts = current_ts;
alloc_row.upid = current_upid;
alloc_row.profile_type = profile_type;
alloc_row.depth = depth;
- alloc_row.name = MaybeDeobfuscate(StringId::Raw(node.class_name));
+ alloc_row.name = *name;
alloc_row.map_name = java_mapping;
alloc_row.count = static_cast<int64_t>(node.count);
alloc_row.cumulative_count =
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
index e68209b..6623235 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.h
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.h
@@ -21,6 +21,7 @@
#include <vector>
#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/string_view.h"
#include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
#include "src/trace_processor/importers/proto/heap_graph_walker.h"
@@ -103,7 +104,8 @@
StringPool::Id deobfuscated_name);
StringPool::Id MaybeDeobfuscate(StringPool::Id);
- const std::vector<int64_t>* RowsForType(StringPool::Id type_name) const {
+ const std::vector<tables::HeapGraphClassTable::Id>* RowsForType(
+ StringPool::Id type_name) const {
auto it = class_to_rows_.find(type_name);
if (it == class_to_rows_.end())
return nullptr;
@@ -152,7 +154,8 @@
std::map<uint32_t, SequenceState> sequence_state_;
std::map<std::pair<UniquePid, int64_t /* ts */>, HeapGraphWalker> walkers_;
- std::map<StringPool::Id, std::vector<int64_t>> class_to_rows_;
+ std::map<StringPool::Id, std::vector<tables::HeapGraphClassTable::Id>>
+ class_to_rows_;
std::map<StringPool::Id, std::vector<int64_t>> field_to_rows_;
std::map<StringPool::Id, StringPool::Id> deobfuscation_mapping_;
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.cc b/src/trace_processor/importers/proto/heap_graph_walker.cc
index fc9e415..0082a3f 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker.cc
@@ -59,7 +59,9 @@
HeapGraphWalker::Delegate::~Delegate() = default;
-void HeapGraphWalker::AddNode(int64_t row, uint64_t size, uint32_t class_name) {
+void HeapGraphWalker::AddNode(int64_t row,
+ uint64_t size,
+ ClassNameId class_name) {
if (static_cast<size_t>(row) >= nodes_.size())
nodes_.resize(static_cast<size_t>(row) + 1);
Node& node = GetNode(row);
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.h b/src/trace_processor/importers/proto/heap_graph_walker.h
index e034f1a..128aa57 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.h
+++ b/src/trace_processor/importers/proto/heap_graph_walker.h
@@ -97,7 +97,7 @@
class HeapGraphWalker {
public:
- using ClassNameId = uint32_t;
+ using ClassNameId = int64_t;
struct PathFromRoot {
static constexpr size_t kRoot = 0;
@@ -149,7 +149,7 @@
uint64_t lowlink = 0;
int64_t component = -1;
- uint32_t class_name = 0;
+ ClassNameId class_name = 0;
int32_t distance_to_root = -1;
bool on_stack = false;
diff --git a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
index 322fd5a..3a55dda 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
@@ -596,7 +596,7 @@
}
bool HasPath(const HeapGraphWalker::PathFromRoot& path,
- std::vector<uint32_t> class_names) {
+ std::vector<HeapGraphWalker::ClassNameId> class_names) {
return HasPath(path, path.nodes[HeapGraphWalker::PathFromRoot::kRoot],
std::move(class_names));
}
diff --git a/src/trace_processor/metrics/android/java_heap_histogram.sql b/src/trace_processor/metrics/android/java_heap_histogram.sql
index b6832c0..a8d9b5f 100644
--- a/src/trace_processor/metrics/android/java_heap_histogram.sql
+++ b/src/trace_processor/metrics/android/java_heap_histogram.sql
@@ -21,12 +21,12 @@
-- Base histogram table
heap_obj_histograms AS (
SELECT
- upid,
- graph_sample_ts,
- IFNULL(deobfuscated_type_name, type_name) AS type_name,
+ o.upid,
+ o.graph_sample_ts,
+ IFNULL(c.deobfuscated_name, c.name) AS type_name,
COUNT(1) obj_count,
- SUM(CASE reachable WHEN TRUE THEN 1 ELSE 0 END) reachable_obj_count
- FROM heap_graph_object
+ SUM(CASE o.reachable WHEN TRUE THEN 1 ELSE 0 END) reachable_obj_count
+ FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id
GROUP BY 1, 2, 3
),
-- Group by to build the repeated field by upid, ts
diff --git a/src/trace_processor/metrics/android/unmapped_java_symbols.sql b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
index 0fc8443..1b7f829 100644
--- a/src/trace_processor/metrics/android/unmapped_java_symbols.sql
+++ b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
@@ -22,9 +22,9 @@
FROM (
SELECT
upid,
- RTRIM(REPLACE(type_name, 'java.lang.Class<', ''), '[]>') AS type_name
- FROM heap_graph_object
- WHERE deobfuscated_type_name IS NULL
+ RTRIM(REPLACE(c.name, 'java.lang.Class<', ''), '[]>') AS type_name
+ FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id
+ WHERE c.deobfuscated_name IS NULL
)
WHERE type_name NOT IN ('byte', 'char', 'short', 'int', 'long', 'boolean', 'float', 'double')
AND type_name NOT LIKE '$Proxy%'
@@ -43,9 +43,10 @@
CREATE TABLE IF NOT EXISTS fields_per_upid AS
WITH distinct_unmapped_field_names AS (
- SELECT DISTINCT upid, field_type_name, field_name
- FROM heap_graph_object JOIN heap_graph_reference USING (reference_set_id)
- WHERE deobfuscated_type_name IS NULL
+ SELECT DISTINCT o.upid, field_type_name, field_name
+ FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id
+ JOIN heap_graph_reference USING (reference_set_id)
+ WHERE c.deobfuscated_name IS NULL
AND field_name NOT LIKE '$Proxy%'
AND field_name NOT LIKE 'java.%'
AND field_name NOT LIKE 'javax.%'
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index 733a780..95d6d94 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -534,6 +534,13 @@
tables::HeapGraphObjectTable* mutable_heap_graph_object_table() {
return &heap_graph_object_table_;
}
+ const tables::HeapGraphClassTable& heap_graph_class_table() const {
+ return heap_graph_class_table_;
+ }
+
+ tables::HeapGraphClassTable* mutable_heap_graph_class_table() {
+ return &heap_graph_class_table_;
+ }
const tables::HeapGraphReferenceTable& heap_graph_reference_table() const {
return heap_graph_reference_table_;
@@ -772,6 +779,7 @@
// Symbol tables (mappings from frames to symbol names)
tables::SymbolTable symbol_table_{&string_pool_, nullptr};
tables::HeapGraphObjectTable heap_graph_object_table_{&string_pool_, nullptr};
+ tables::HeapGraphClassTable heap_graph_class_table_{&string_pool_, nullptr};
tables::HeapGraphReferenceTable heap_graph_reference_table_{&string_pool_,
nullptr};
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index b58c908..e4d6ba5 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -118,19 +118,27 @@
PERFETTO_TP_TABLE(PERFETTO_TP_EXPERIMENTAL_FLAMEGRAPH_NODES);
-#define PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF(NAME, PARENT, C) \
- NAME(HeapGraphObjectTable, "heap_graph_object") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(uint32_t, upid) \
- C(int64_t, graph_sample_ts) \
- C(int64_t, object_id) \
- C(int64_t, self_size) \
- C(int64_t, retained_size) \
- C(int64_t, unique_retained_size) \
- C(base::Optional<uint32_t>, reference_set_id) \
- C(int32_t, reachable) \
- C(StringPool::Id, type_name) \
- C(base::Optional<StringPool::Id>, deobfuscated_type_name) \
+#define PERFETTO_TP_HEAP_GRAPH_CLASS_DEF(NAME, PARENT, C) \
+ NAME(HeapGraphClassTable, "heap_graph_class") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(StringPool::Id, name) \
+ C(base::Optional<StringPool::Id>, deobfuscated_name) \
+ C(base::Optional<StringPool::Id>, location)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_GRAPH_CLASS_DEF);
+
+#define PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF(NAME, PARENT, C) \
+ NAME(HeapGraphObjectTable, "heap_graph_object") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(uint32_t, upid) \
+ C(int64_t, graph_sample_ts) \
+ C(int64_t, object_id) \
+ C(int64_t, self_size) \
+ C(int64_t, retained_size) \
+ C(int64_t, unique_retained_size) \
+ C(base::Optional<uint32_t>, reference_set_id) \
+ C(int32_t, reachable) \
+ C(HeapGraphClassTable::Id, type_id) \
C(base::Optional<StringPool::Id>, root_type)
PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF);
diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc
index 8e6dd44..50953fb 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -51,6 +51,7 @@
HeapProfileAllocationTable::~HeapProfileAllocationTable() = default;
ExperimentalFlamegraphNodesTable::~ExperimentalFlamegraphNodesTable() = default;
HeapGraphObjectTable::~HeapGraphObjectTable() = default;
+HeapGraphClassTable::~HeapGraphClassTable() = default;
HeapGraphReferenceTable::~HeapGraphReferenceTable() = default;
VulkanMemoryAllocationsTable::~VulkanMemoryAllocationsTable() = default;
PackageListTable::~PackageListTable() = default;
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index e90f50d..c44a56c 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -528,6 +528,7 @@
RegisterDbTable(storage->heap_graph_object_table());
RegisterDbTable(storage->heap_graph_reference_table());
+ RegisterDbTable(storage->heap_graph_class_table());
RegisterDbTable(storage->symbol_table());
RegisterDbTable(storage->heap_profile_allocation_table());
diff --git a/test/trace_processor/heap_graph_object.sql b/test/trace_processor/heap_graph_object.sql
index 234728f..d84ea66 100644
--- a/test/trace_processor/heap_graph_object.sql
+++ b/test/trace_processor/heap_graph_object.sql
@@ -13,4 +13,17 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-select * from heap_graph_object
+select o.id,
+ o.type,
+ o.upid,
+ o.graph_sample_ts,
+ o.object_id,
+ o.self_size,
+ o.retained_size,
+ o.unique_retained_size,
+ o.reference_set_id,
+ o.reachable,
+ c.name as type_name,
+ c.deobfuscated_name as deobfuscated_type_name,
+ o.root_type
+from heap_graph_object o join heap_graph_class c on o.type_id = c.id