1#!/usr/bin/env python3 2# Copyright (C) 2023 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 a 7# 8# http://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 16from python.generators.diff_tests.testing import Path, DataPath, Metric 17from python.generators.diff_tests.testing import Csv, Json, TextProto 18from python.generators.diff_tests.testing import DiffTestBlueprint 19from python.generators.diff_tests.testing import TestSuite 20 21 22class ProfilingHeapGraph(TestSuite): 23 24 def test_heap_graph_flamegraph(self): 25 return DiffTestBlueprint( 26 trace=Path('heap_graph_baseapk.textproto'), 27 query=""" 28 SELECT 29 id, 30 depth, 31 name, 32 map_name, 33 count, 34 cumulative_count, 35 size, 36 cumulative_size, 37 parent_id 38 FROM experimental_flamegraph 39 WHERE upid = (SELECT max(upid) FROM heap_graph_object) 40 AND profile_type = 'graph' 41 AND ts = (SELECT max(graph_sample_ts) FROM heap_graph_object) 42 LIMIT 10; 43 """, 44 out=Path('heap_graph_flamegraph.out')) 45 46 def test_heap_graph_object(self): 47 return DiffTestBlueprint( 48 trace=Path('heap_graph_baseapk.textproto'), 49 query=""" 50 SELECT o.id, 51 o.type, 52 o.upid, 53 o.graph_sample_ts, 54 o.self_size, 55 o.reference_set_id, 56 o.reachable, 57 c.name AS type_name, 58 c.deobfuscated_name AS deobfuscated_type_name, 59 o.root_type 60 FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id; 61 """, 62 out=Path('heap_graph_object.out')) 63 64 def test_heap_graph_reference(self): 65 return DiffTestBlueprint( 66 trace=Path('heap_graph_baseapk.textproto'), 67 query=""" 68 SELECT * FROM heap_graph_reference; 69 """, 70 out=Path('heap_graph_reference.out')) 71 72 def test_heap_graph_object_2(self): 73 return DiffTestBlueprint( 74 trace=Path('heap_graph_deobfuscate_pkg.textproto'), 75 query=""" 76 SELECT o.id, 77 o.type, 78 o.upid, 79 o.graph_sample_ts, 80 o.self_size, 81 o.reference_set_id, 82 o.reachable, 83 c.name AS type_name, 84 c.deobfuscated_name AS deobfuscated_type_name, 85 o.root_type 86 FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id; 87 """, 88 out=Path('heap_graph_object.out')) 89 90 def test_heap_graph_duplicate_flamegraph(self): 91 return DiffTestBlueprint( 92 trace=TextProto(r""" 93 packet { 94 process_tree { 95 processes { 96 pid: 2 97 ppid: 1 98 cmdline: "system_server" 99 uid: 1000 100 } 101 } 102 } 103 packet { 104 timestamp: 10 105 process_stats { 106 processes { 107 pid: 2 108 rss_anon_kb: 1000 109 vm_swap_kb: 3000 110 oom_score_adj: 0 111 } 112 } 113 } 114 packet { 115 trusted_packet_sequence_id: 999 116 timestamp: 10 117 heap_graph { 118 pid: 2 119 types { 120 id: 1 121 class_name: "FactoryProducerDelegateImplActor" 122 location_id: 1 123 } 124 roots { 125 root_type: ROOT_JAVA_FRAME 126 object_ids: 0x01 127 object_ids: 0x01 128 } 129 objects { 130 id: 0x01 131 type_id: 1 132 self_size: 64 133 } 134 continued: false 135 index: 0 136 } 137 } 138 """), 139 query=""" 140 SELECT 141 id, 142 depth, 143 name, 144 map_name, 145 count, 146 cumulative_count, 147 size, 148 cumulative_size, 149 parent_id 150 FROM experimental_flamegraph 151 WHERE upid = (SELECT max(upid) FROM heap_graph_object) 152 AND profile_type = 'graph' 153 AND ts = (SELECT max(graph_sample_ts) FROM heap_graph_object) 154 LIMIT 10; 155 """, 156 out=Path('heap_graph_duplicate_flamegraph.out')) 157 158 def test_heap_graph_flamegraph_2(self): 159 return DiffTestBlueprint( 160 trace=Path('heap_graph.textproto'), 161 query=""" 162 SELECT 163 id, 164 depth, 165 name, 166 map_name, 167 count, 168 cumulative_count, 169 size, 170 cumulative_size, 171 parent_id 172 FROM experimental_flamegraph 173 WHERE upid = (SELECT max(upid) FROM heap_graph_object) 174 AND profile_type = 'graph' 175 AND ts = (SELECT max(graph_sample_ts) FROM heap_graph_object) 176 LIMIT 10; 177 """, 178 out=Path('heap_graph_flamegraph.out')) 179 180 def test_heap_graph_object_3(self): 181 return DiffTestBlueprint( 182 trace=Path('heap_graph.textproto'), 183 query=""" 184 SELECT o.id, 185 o.type, 186 o.upid, 187 o.graph_sample_ts, 188 o.self_size, 189 o.reference_set_id, 190 o.reachable, 191 c.name AS type_name, 192 c.deobfuscated_name AS deobfuscated_type_name, 193 o.root_type 194 FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id; 195 """, 196 out=Path('heap_graph_object.out')) 197 198 def test_heap_graph_reference_2(self): 199 return DiffTestBlueprint( 200 trace=Path('heap_graph.textproto'), 201 query=""" 202 SELECT * FROM heap_graph_reference; 203 """, 204 out=Path('heap_graph_reference.out')) 205 206 def test_heap_graph_two_locations(self): 207 return DiffTestBlueprint( 208 trace=Path('heap_graph_two_locations.textproto'), 209 query=""" 210 SELECT o.id, 211 o.type, 212 o.upid, 213 o.graph_sample_ts, 214 o.self_size, 215 o.reference_set_id, 216 o.reachable, 217 c.name AS type_name, 218 c.deobfuscated_name AS deobfuscated_type_name, 219 o.root_type 220 FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id; 221 """, 222 out=Path('heap_graph_two_locations.out')) 223 224 def test_heap_graph_object_4(self): 225 return DiffTestBlueprint( 226 trace=Path('heap_graph_legacy.textproto'), 227 query=""" 228 SELECT o.id, 229 o.type, 230 o.upid, 231 o.graph_sample_ts, 232 o.self_size, 233 o.reference_set_id, 234 o.reachable, 235 c.name AS type_name, 236 c.deobfuscated_name AS deobfuscated_type_name, 237 o.root_type 238 FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id; 239 """, 240 out=Path('heap_graph_object.out')) 241 242 def test_heap_graph_reference_3(self): 243 return DiffTestBlueprint( 244 trace=Path('heap_graph_legacy.textproto'), 245 query=""" 246 SELECT * FROM heap_graph_reference; 247 """, 248 out=Path('heap_graph_reference.out')) 249 250 def test_heap_graph_interleaved_object(self): 251 return DiffTestBlueprint( 252 trace=Path('heap_graph_interleaved.textproto'), 253 query=""" 254 SELECT o.id, 255 o.type, 256 o.upid, 257 o.graph_sample_ts, 258 o.self_size, 259 o.reference_set_id, 260 o.reachable, 261 c.name AS type_name, 262 c.deobfuscated_name AS deobfuscated_type_name, 263 o.root_type 264 FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id; 265 """, 266 out=Path('heap_graph_interleaved_object.out')) 267 268 def test_heap_graph_interleaved_reference(self): 269 return DiffTestBlueprint( 270 trace=Path('heap_graph_interleaved.textproto'), 271 query=""" 272 SELECT * FROM heap_graph_reference; 273 """, 274 out=Path('heap_graph_interleaved_reference.out')) 275 276 def test_heap_graph_flamegraph_system_server_heap_graph(self): 277 return DiffTestBlueprint( 278 trace=DataPath('system-server-heap-graph-new.pftrace'), 279 query=""" 280 SELECT 281 id, 282 depth, 283 name, 284 map_name, 285 count, 286 cumulative_count, 287 size, 288 cumulative_size, 289 parent_id 290 FROM experimental_flamegraph 291 WHERE upid = (SELECT max(upid) FROM heap_graph_object) 292 AND profile_type = 'graph' 293 AND ts = (SELECT max(graph_sample_ts) FROM heap_graph_object) 294 LIMIT 10; 295 """, 296 out=Path('heap_graph_flamegraph_system-server-heap-graph.out')) 297 298 def test_heap_profile_flamegraph_system_server_native_profile(self): 299 return DiffTestBlueprint( 300 trace=DataPath('system-server-native-profile'), 301 query=""" 302 SELECT * FROM experimental_flamegraph 303 WHERE ts = 605908369259172 304 AND upid = 1 305 AND profile_type = 'native' 306 LIMIT 10; 307 """, 308 out=Path('heap_profile_flamegraph_system-server-native-profile.out')) 309 310 def test_heap_profile_tracker_new_stack(self): 311 return DiffTestBlueprint( 312 trace=Path('heap_profile_tracker_new_stack.textproto'), 313 query=""" 314 SELECT * FROM heap_profile_allocation; 315 """, 316 out=Csv(""" 317 "id","type","ts","upid","heap_name","callsite_id","count","size" 318 0,"heap_profile_allocation",0,0,"malloc",0,1,1 319 1,"heap_profile_allocation",0,0,"malloc",0,-1,-1 320 2,"heap_profile_allocation",1,0,"malloc",0,1,1 321 3,"heap_profile_allocation",1,0,"malloc",0,-1,-1 322 """)) 323 324 def test_heap_profile_tracker_twoheaps(self): 325 return DiffTestBlueprint( 326 trace=Path('heap_profile_tracker_twoheaps.textproto'), 327 query=""" 328 SELECT * FROM heap_profile_allocation; 329 """, 330 out=Csv(""" 331 "id","type","ts","upid","heap_name","callsite_id","count","size" 332 0,"heap_profile_allocation",0,0,"malloc",0,1,1 333 1,"heap_profile_allocation",0,0,"malloc",0,-1,-1 334 2,"heap_profile_allocation",0,0,"custom",0,1,1 335 3,"heap_profile_allocation",0,0,"custom",0,-1,-1 336 """)) 337 338 def test_heap_graph_flamegraph_focused(self): 339 return DiffTestBlueprint( 340 trace=Path('heap_graph_branching.textproto'), 341 query=""" 342 SELECT 343 id, 344 depth, 345 name, 346 count, 347 cumulative_count, 348 size, 349 cumulative_size, 350 parent_id 351 FROM experimental_flamegraph 352 WHERE upid = (SELECT max(upid) FROM heap_graph_object) 353 AND profile_type = 'graph' 354 AND ts = (SELECT max(graph_sample_ts) FROM heap_graph_object) 355 AND focus_str = 'left' 356 LIMIT 10; 357 """, 358 out=Path('heap_graph_flamegraph_focused.out')) 359 360 def test_heap_graph_superclass(self): 361 return DiffTestBlueprint( 362 trace=Path('heap_graph_superclass.textproto'), 363 query=""" 364 SELECT c.id, c.superclass_id, c.name, s.name AS superclass_name, c.location 365 FROM heap_graph_class c LEFT JOIN heap_graph_class s ON c.superclass_id = s.id; 366 """, 367 out=Csv(""" 368 "id","superclass_id","name","superclass_name","location" 369 0,"[NULL]","java.lang.Class<java.lang.Object>","[NULL]","l1" 370 1,"[NULL]","java.lang.Class<MySuperClass>","[NULL]","l1" 371 2,"[NULL]","java.lang.Class<MyChildClass>","[NULL]","l2" 372 3,"[NULL]","java.lang.Object","[NULL]","l1" 373 4,3,"MySuperClass","java.lang.Object","l1" 374 5,4,"MyChildClass","MySuperClass","l2" 375 """)) 376 377 def test_heap_graph_native_size(self): 378 return DiffTestBlueprint( 379 trace=Path('heap_graph_native_size.textproto'), 380 query=""" 381 SELECT c.name AS type_name, 382 o.native_size 383 FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id 384 WHERE o.root_type = "ROOT_JAVA_FRAME"; 385 """, 386 out=Csv(""" 387 "type_name","native_size" 388 "android.graphics.Bitmap",123456 389 "android.os.BinderProxy",0 390 """)) 391