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.dominator_tree; 17 18INCLUDE PERFETTO MODULE graphs.partition; 19 20CREATE PERFETTO FUNCTION _partition_tree_super_root_fn() 21-- The assigned id of the "super root". 22RETURNS LONG AS 23SELECT 24 id + 1 25FROM heap_graph_object 26ORDER BY 27 id DESC 28LIMIT 1; 29 30CREATE PERFETTO FUNCTION _is_libcore_or_array( 31 obj_name STRING 32) 33RETURNS BOOL AS 34SELECT 35 ( 36 $obj_name GLOB 'java.*' AND NOT $obj_name GLOB 'java.lang.Class<*>' 37 ) 38 OR $obj_name GLOB 'j$.*' 39 OR $obj_name GLOB 'int[[]*' 40 OR $obj_name GLOB 'long[[]*' 41 OR $obj_name GLOB 'byte[[]*' 42 OR $obj_name GLOB 'char[[]*' 43 OR $obj_name GLOB 'short[[]*' 44 OR $obj_name GLOB 'float[[]*' 45 OR $obj_name GLOB 'double[[]*' 46 OR $obj_name GLOB 'boolean[[]*' 47 OR $obj_name GLOB 'android.util.*Array*'; 48 49CREATE PERFETTO TABLE _heap_graph_dominator_tree_for_partition AS 50SELECT 51 tree.id, 52 coalesce(tree.idom_id, _partition_tree_super_root_fn()) AS parent_id, 53 obj.type_id AS group_key 54FROM heap_graph_dominator_tree AS tree 55JOIN heap_graph_object AS obj 56 USING (id) 57UNION ALL 58-- provide a single root required by tree partition if heap graph exists. 59SELECT 60 _partition_tree_super_root_fn() AS id, 61 NULL AS parent_id, 62 ( 63 SELECT 64 id + 1 65 FROM heap_graph_class 66 ORDER BY 67 id DESC 68 LIMIT 1 69 ) AS group_key 70WHERE 71 _partition_tree_super_root_fn() IS NOT NULL; 72 73CREATE PERFETTO TABLE _heap_object_marked_for_dominated_stats AS 74SELECT 75 id, 76 iif(parent_id IS NULL, 1, 0) AS marked 77FROM tree_structural_partition_by_group!(_heap_graph_dominator_tree_for_partition) 78ORDER BY 79 id; 80 81-- Class-level breakdown of the java heap. 82-- Per type name aggregates the object stats and the dominator tree stats. 83CREATE PERFETTO TABLE android_heap_graph_class_aggregation ( 84 -- Process upid 85 upid JOINID(process.id), 86 -- Heap dump timestamp 87 graph_sample_ts TIMESTAMP, 88 -- Class type id 89 type_id LONG, 90 -- Class name (deobfuscated if available) 91 type_name STRING, 92 -- Is type an instance of a libcore object (java.*) or array 93 is_libcore_or_array BOOL, 94 -- Count of class instances 95 obj_count LONG, 96 -- Size of class instances 97 size_bytes LONG, 98 -- Native size of class instances 99 native_size_bytes LONG, 100 -- Count of reachable class instances 101 reachable_obj_count LONG, 102 -- Size of reachable class instances 103 reachable_size_bytes LONG, 104 -- Native size of reachable class instances 105 reachable_native_size_bytes LONG, 106 -- Count of all objects dominated by instances of this class 107 -- Only applies to reachable objects 108 dominated_obj_count LONG, 109 -- Size of all objects dominated by instances of this class 110 -- Only applies to reachable objects 111 dominated_size_bytes LONG, 112 -- Native size of all objects dominated by instances of this class 113 -- Only applies to reachable objects 114 dominated_native_size_bytes LONG 115) AS 116WITH 117 base AS ( 118 -- First level aggregation to avoid joining with class for every object 119 SELECT 120 obj.upid, 121 obj.graph_sample_ts, 122 obj.type_id, 123 count(1) AS obj_count, 124 sum(self_size) AS size_bytes, 125 sum(native_size) AS native_size_bytes, 126 sum(iif(obj.reachable, 1, 0)) AS reachable_obj_count, 127 sum(iif(obj.reachable, self_size, 0)) AS reachable_size_bytes, 128 sum(iif(obj.reachable, native_size, 0)) AS reachable_native_size_bytes, 129 sum(iif(marked, dominated_obj_count, 0)) AS dominated_obj_count, 130 sum(iif(marked, dominated_size_bytes, 0)) AS dominated_size_bytes, 131 sum(iif(marked, dominated_native_size_bytes, 0)) AS dominated_native_size_bytes 132 FROM heap_graph_object AS obj 133 -- Left joins to preserve unreachable objects. 134 LEFT JOIN _heap_object_marked_for_dominated_stats 135 USING (id) 136 LEFT JOIN heap_graph_dominator_tree 137 USING (id) 138 GROUP BY 139 1, 140 2, 141 3 142 ORDER BY 143 1, 144 2, 145 3 146 ) 147SELECT 148 upid, 149 graph_sample_ts, 150 type_id, 151 coalesce(cls.deobfuscated_name, cls.name) AS type_name, 152 _is_libcore_or_array(coalesce(cls.deobfuscated_name, cls.name)) AS is_libcore_or_array, 153 sum(obj_count) AS obj_count, 154 sum(size_bytes) AS size_bytes, 155 sum(native_size_bytes) AS native_size_bytes, 156 sum(reachable_obj_count) AS reachable_obj_count, 157 sum(reachable_size_bytes) AS reachable_size_bytes, 158 sum(reachable_native_size_bytes) AS reachable_native_size_bytes, 159 sum(dominated_obj_count) AS dominated_obj_count, 160 sum(dominated_size_bytes) AS dominated_size_bytes, 161 sum(dominated_native_size_bytes) AS dominated_native_size_bytes 162FROM base 163JOIN heap_graph_class AS cls 164 ON base.type_id = cls.id 165GROUP BY 166 1, 167 2, 168 3, 169 4, 170 5 171ORDER BY 172 1, 173 2, 174 3, 175 4, 176 5; 177