1-- 2-- Copyright 2024 The Android Open Source Project 3-- 4-- Licensed under the Apache License, Version 2.0 (the "License"); 5-- you may not use this file except in compliance with the License. 6-- You may obtain a copy of the License at 7-- 8-- https://www.apache.org/licenses/LICENSE-2.0 9-- 10-- Unless required by applicable law or agreed to in writing, software 11-- distributed under the License is distributed ON an "AS IS" BASIS, 12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13-- See the License for the specific language governing permissions and 14-- limitations under the License. 15 16INCLUDE PERFETTO MODULE android.memory.heap_graph.excluded_refs; 17 18INCLUDE PERFETTO MODULE android.memory.heap_graph.helpers; 19 20INCLUDE PERFETTO MODULE graphs.search; 21 22-- Converts the heap graph into a tree by performing a BFS on the graph from 23-- the roots. This basically ends up with all paths being the shortest path 24-- from the root to the node (with lower ids being picked in the case of ties). 25CREATE PERFETTO TABLE _heap_graph_object_min_depth_tree AS 26SELECT 27 node_id AS id, 28 parent_node_id AS parent_id 29FROM graph_reachable_bfs!( 30 ( 31 SELECT owner_id AS source_node_id, owned_id AS dest_node_id 32 FROM heap_graph_reference ref 33 WHERE ref.id NOT IN _excluded_refs AND ref.owned_id IS NOT NULL 34 ORDER BY ref.owned_id 35 ), 36 ( 37 SELECT id AS node_id 38 FROM heap_graph_object 39 WHERE root_type IS NOT NULL 40 ) 41) 42ORDER BY 43 id; 44 45CREATE PERFETTO TABLE _heap_graph_path_hashes AS 46SELECT 47 * 48FROM _heap_graph_type_path_hash!(_heap_graph_object_min_depth_tree); 49 50CREATE PERFETTO TABLE _heap_graph_path_hashes_aggregated AS 51SELECT 52 * 53FROM _heap_graph_path_hash_aggregate!(_heap_graph_path_hashes); 54 55CREATE PERFETTO TABLE _heap_graph_class_tree AS 56SELECT 57 * 58FROM _heap_graph_path_hashes_to_class_tree!(_heap_graph_path_hashes_aggregated); 59 60CREATE PERFETTO MACRO _heap_graph_object_references_agg( 61 path_hashes TableOrSubquery, 62 path_hash_values TableOrSubquery 63) 64RETURNS TableOrSubquery AS 65( 66 WITH 67 _path_hashes AS ( 68 SELECT 69 * 70 FROM $path_hashes 71 JOIN $path_hash_values 72 USING (path_hash) 73 ) 74 SELECT 75 path_hash, 76 c.name AS class_name, 77 count(r.owned_id) AS outgoing_reference_count, 78 o.* 79 FROM _path_hashes AS h 80 JOIN heap_graph_object AS o 81 ON h.id = o.id 82 JOIN heap_graph_class AS c 83 ON o.type_id = c.id 84 JOIN heap_graph_reference AS r 85 ON r.owner_id = o.id 86 GROUP BY 87 o.id 88 ORDER BY 89 outgoing_reference_count DESC 90); 91 92CREATE PERFETTO MACRO _heap_graph_incoming_references_agg( 93 path_hashes TableOrSubquery, 94 path_hash_values TableOrSubquery 95) 96RETURNS TableOrSubquery AS 97( 98 WITH 99 _path_hashes AS ( 100 SELECT 101 * 102 FROM $path_hashes 103 JOIN $path_hash_values 104 USING (path_hash) 105 ) 106 SELECT 107 path_hash, 108 c.name AS class_name, 109 r.field_name, 110 r.field_type_name, 111 src.* 112 FROM _path_hashes AS h 113 JOIN heap_graph_object AS dst 114 ON h.id = dst.id 115 JOIN heap_graph_reference AS r 116 ON r.owned_id = dst.id 117 JOIN heap_graph_object AS src 118 ON r.owner_id = src.id 119 JOIN heap_graph_class AS c 120 ON src.type_id = c.id 121 ORDER BY 122 self_size DESC 123); 124 125CREATE PERFETTO MACRO _heap_graph_outgoing_references_agg( 126 path_hashes TableOrSubquery, 127 path_hash_values TableOrSubquery 128) 129RETURNS TableOrSubquery AS 130( 131 WITH 132 _path_hashes AS ( 133 SELECT 134 * 135 FROM $path_hashes 136 JOIN $path_hash_values 137 USING (path_hash) 138 ) 139 SELECT 140 path_hash, 141 c.name AS class_name, 142 r.field_name, 143 r.field_type_name, 144 dst.* 145 FROM _path_hashes AS h 146 JOIN heap_graph_object AS src 147 ON h.id = src.id 148 JOIN heap_graph_reference AS r 149 ON r.owner_id = src.id 150 JOIN heap_graph_object AS dst 151 ON r.owned_id = dst.id 152 JOIN heap_graph_class AS c 153 ON dst.type_id = c.id 154 ORDER BY 155 dst.self_size DESC 156); 157 158CREATE PERFETTO MACRO _heap_graph_retained_object_count_agg( 159 path_hashes TableOrSubquery, 160 path_hash_values TableOrSubquery 161) 162RETURNS TableOrSubquery AS 163( 164 SELECT 165 c.name AS class_name, 166 o.heap_type, 167 o.root_type, 168 o.reachable, 169 sum(o.self_size) AS total_size, 170 sum(o.native_size) AS total_native_size, 171 count() AS count 172 FROM graph_reachable_bfs 173 !( 174 ( 175 SELECT 176 IFNULL(parent_id, id) AS source_node_id, 177 IFNULL(id, parent_id) AS dest_node_id 178 FROM _heap_graph_object_min_depth_tree 179 ), 180 ( 181 SELECT o.id AS node_id 182 FROM $path_hashes h 183 JOIN heap_graph_object o 184 ON h.id = o.id 185 JOIN heap_graph_class c 186 ON o.type_id = c.id 187 JOIN $path_hash_values USING(path_hash) 188 )) AS b 189 JOIN heap_graph_object AS o 190 ON b.node_id = o.id 191 JOIN heap_graph_class AS c 192 ON o.type_id = c.id 193 GROUP BY 194 class_name, 195 heap_type, 196 root_type, 197 reachable 198 ORDER BY 199 count DESC 200); 201 202CREATE PERFETTO MACRO _heap_graph_retaining_object_count_agg( 203 path_hashes TableOrSubquery, 204 path_hash_values TableOrSubquery 205) 206RETURNS TableOrSubquery AS 207( 208 SELECT 209 c.name AS class_name, 210 o.heap_type, 211 o.root_type, 212 o.reachable, 213 sum(o.self_size) AS total_size, 214 sum(o.native_size) AS total_native_size, 215 count() AS count 216 FROM graph_reachable_bfs 217 !( 218 ( 219 SELECT 220 IFNULL(id, parent_id) AS source_node_id, 221 IFNULL(parent_id, id) AS dest_node_id 222 FROM _heap_graph_object_min_depth_tree 223 ), 224 ( 225 SELECT o.id AS node_id 226 FROM $path_hashes h 227 JOIN heap_graph_object o 228 ON h.id = o.id 229 JOIN heap_graph_class c 230 ON o.type_id = c.id 231 JOIN $path_hash_values USING(path_hash) 232 )) AS b 233 JOIN heap_graph_object AS o 234 ON b.node_id = o.id 235 JOIN heap_graph_class AS c 236 ON o.type_id = c.id 237 GROUP BY 238 class_name, 239 heap_type, 240 root_type, 241 reachable 242 ORDER BY 243 count DESC 244); 245 246CREATE PERFETTO MACRO _heap_graph_duplicate_objects_agg( 247 path_hashes TableOrSubquery 248) 249RETURNS TableOrSubquery AS 250( 251 SELECT 252 count(DISTINCT path_hash) AS path_count, 253 count() AS object_count, 254 sum(o.self_size) AS total_size, 255 sum(o.native_size) AS total_native_size, 256 c.name AS class_name 257 FROM $path_hashes AS h 258 JOIN heap_graph_object AS o 259 ON h.id = o.id 260 JOIN heap_graph_class AS c 261 ON o.type_id = c.id 262 GROUP BY 263 class_name 264 ORDER BY 265 path_count DESC 266); 267