• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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          'graph',
40          (SELECT max(graph_sample_ts) FROM heap_graph_object),
41          NULL,
42          (SELECT max(upid) FROM heap_graph_object),
43          NULL,
44          NULL
45        )
46        LIMIT 10;
47        """,
48        out=Path('heap_graph_flamegraph.out'))
49
50  def test_heap_graph_object(self):
51    return DiffTestBlueprint(
52        trace=Path('heap_graph_baseapk.textproto'),
53        query="""
54        SELECT o.id,
55               o.type,
56               o.upid,
57               o.graph_sample_ts,
58               o.self_size,
59               o.reference_set_id,
60               o.reachable,
61               c.name AS type_name,
62               c.deobfuscated_name AS deobfuscated_type_name,
63               o.root_type
64        FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id;
65        """,
66        out=Path('heap_graph_object.out'))
67
68  def test_heap_graph_reference(self):
69    return DiffTestBlueprint(
70        trace=Path('heap_graph_baseapk.textproto'),
71        query="""
72        SELECT * FROM heap_graph_reference;
73        """,
74        out=Path('heap_graph_reference.out'))
75
76  def test_heap_graph_object_2(self):
77    return DiffTestBlueprint(
78        trace=Path('heap_graph_deobfuscate_pkg.textproto'),
79        query="""
80        SELECT o.id,
81               o.type,
82               o.upid,
83               o.graph_sample_ts,
84               o.self_size,
85               o.reference_set_id,
86               o.reachable,
87               c.name AS type_name,
88               c.deobfuscated_name AS deobfuscated_type_name,
89               o.root_type
90        FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id;
91        """,
92        out=Path('heap_graph_object.out'))
93
94  def test_heap_graph_duplicate_flamegraph(self):
95    return DiffTestBlueprint(
96        trace=TextProto(r"""
97        packet {
98          process_tree {
99            processes {
100              pid: 2
101              ppid: 1
102              cmdline: "system_server"
103              uid: 1000
104            }
105          }
106        }
107        packet {
108          timestamp: 10
109          process_stats {
110            processes {
111              pid: 2
112              rss_anon_kb: 1000
113              vm_swap_kb: 3000
114              oom_score_adj: 0
115            }
116          }
117        }
118        packet {
119          trusted_packet_sequence_id: 999
120          timestamp: 10
121          heap_graph {
122            pid: 2
123            types {
124              id: 1
125              class_name: "FactoryProducerDelegateImplActor"
126              location_id: 1
127            }
128            roots {
129              root_type: ROOT_JAVA_FRAME
130              object_ids: 0x01
131              object_ids: 0x01
132            }
133            objects {
134              id: 0x01
135              type_id: 1
136              self_size: 64
137            }
138            continued: false
139            index: 0
140          }
141        }
142        """),
143        query="""
144        SELECT
145          id,
146          depth,
147          name,
148          map_name,
149          count,
150          cumulative_count,
151          size,
152          cumulative_size,
153          parent_id
154        FROM experimental_flamegraph(
155          'graph',
156          (SELECT max(graph_sample_ts) FROM heap_graph_object),
157          NULL,
158          (SELECT max(upid) FROM heap_graph_object),
159          NULL,
160          NULL
161        )
162        LIMIT 10;
163        """,
164        out=Path('heap_graph_duplicate_flamegraph.out'))
165
166  def test_heap_graph_flamegraph_2(self):
167    return DiffTestBlueprint(
168        trace=Path('heap_graph.textproto'),
169        query="""
170        SELECT
171          id,
172          depth,
173          name,
174          map_name,
175          count,
176          cumulative_count,
177          size,
178          cumulative_size,
179          parent_id
180        FROM experimental_flamegraph(
181          'graph',
182          (SELECT max(graph_sample_ts) FROM heap_graph_object),
183          NULL,
184          (SELECT max(upid) FROM heap_graph_object),
185          NULL,
186          NULL
187        )
188        LIMIT 10;
189        """,
190        out=Path('heap_graph_flamegraph.out'))
191
192  def test_heap_graph_object_3(self):
193    return DiffTestBlueprint(
194        trace=Path('heap_graph.textproto'),
195        query="""
196        SELECT o.id,
197               o.type,
198               o.upid,
199               o.graph_sample_ts,
200               o.self_size,
201               o.reference_set_id,
202               o.reachable,
203               c.name AS type_name,
204               c.deobfuscated_name AS deobfuscated_type_name,
205               o.root_type
206        FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id;
207        """,
208        out=Path('heap_graph_object.out'))
209
210  def test_heap_graph_object_reference_set_id(self):
211    return DiffTestBlueprint(
212        trace=Path('heap_graph.textproto'),
213        query="""
214        SELECT o.reference_set_id
215        FROM heap_graph_object o
216        WHERE o.reference_set_id = 3
217        """,
218        out=Csv('''
219          "reference_set_id"
220          3
221        '''))
222
223  def test_heap_graph_reference_2(self):
224    return DiffTestBlueprint(
225        trace=Path('heap_graph.textproto'),
226        query="""
227        SELECT * FROM heap_graph_reference;
228        """,
229        out=Path('heap_graph_reference.out'))
230
231  def test_heap_graph_two_locations(self):
232    return DiffTestBlueprint(
233        trace=Path('heap_graph_two_locations.textproto'),
234        query="""
235        SELECT o.id,
236               o.type,
237               o.upid,
238               o.graph_sample_ts,
239               o.self_size,
240               o.reference_set_id,
241               o.reachable,
242               c.name AS type_name,
243               c.deobfuscated_name AS deobfuscated_type_name,
244               o.root_type
245        FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id;
246        """,
247        out=Path('heap_graph_two_locations.out'))
248
249  def test_heap_graph_object_4(self):
250    return DiffTestBlueprint(
251        trace=Path('heap_graph_legacy.textproto'),
252        query="""
253        SELECT o.id,
254               o.type,
255               o.upid,
256               o.graph_sample_ts,
257               o.self_size,
258               o.reference_set_id,
259               o.reachable,
260               c.name AS type_name,
261               c.deobfuscated_name AS deobfuscated_type_name,
262               o.root_type
263        FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id;
264        """,
265        out=Path('heap_graph_object.out'))
266
267  def test_heap_graph_reference_3(self):
268    return DiffTestBlueprint(
269        trace=Path('heap_graph_legacy.textproto'),
270        query="""
271        SELECT * FROM heap_graph_reference;
272        """,
273        out=Path('heap_graph_reference.out'))
274
275  def test_heap_graph_interleaved_object(self):
276    return DiffTestBlueprint(
277        trace=Path('heap_graph_interleaved.textproto'),
278        query="""
279        SELECT o.id,
280               o.type,
281               o.upid,
282               o.graph_sample_ts,
283               o.self_size,
284               o.reference_set_id,
285               o.reachable,
286               c.name AS type_name,
287               c.deobfuscated_name AS deobfuscated_type_name,
288               o.root_type
289        FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id;
290        """,
291        out=Path('heap_graph_interleaved_object.out'))
292
293  def test_heap_graph_interleaved_reference(self):
294    return DiffTestBlueprint(
295        trace=Path('heap_graph_interleaved.textproto'),
296        query="""
297        SELECT * FROM heap_graph_reference;
298        """,
299        out=Path('heap_graph_interleaved_reference.out'))
300
301  def test_heap_graph_flamegraph_system_server_heap_graph(self):
302    return DiffTestBlueprint(
303        trace=DataPath('system-server-heap-graph-new.pftrace'),
304        query="""
305        SELECT
306          id,
307          depth,
308          name,
309          map_name,
310          count,
311          cumulative_count,
312          size,
313          cumulative_size,
314          parent_id
315        FROM experimental_flamegraph(
316          'graph',
317          (SELECT max(graph_sample_ts) FROM heap_graph_object),
318          NULL,
319          (SELECT max(upid) FROM heap_graph_object),
320          NULL,
321          NULL
322        )
323        LIMIT 10;
324        """,
325        out=Path('heap_graph_flamegraph_system-server-heap-graph.out'))
326
327  def test_heap_profile_flamegraph_system_server_native_profile(self):
328    return DiffTestBlueprint(
329        trace=DataPath('system-server-native-profile'),
330        query="""
331        SELECT *
332        FROM experimental_flamegraph(
333          'native',
334          605908369259172,
335          NULL,
336          1,
337          NULL,
338          NULL
339        )
340        LIMIT 10;
341        """,
342        out=Csv('''
343          "id","type","ts","depth","name","map_name","count","cumulative_count","size","cumulative_size","alloc_count","cumulative_alloc_count","alloc_size","cumulative_alloc_size","parent_id","source_file","line_number"
344          0,"experimental_flamegraph",605908369259172,0,"__start_thread","/apex/com.android.runtime/lib64/bionic/libc.so",0,8,0,84848,0,210,0,1084996,"[NULL]","[NULL]","[NULL]"
345          1,"experimental_flamegraph",605908369259172,1,"_ZL15__pthread_startPv","/apex/com.android.runtime/lib64/bionic/libc.so",0,8,0,84848,0,210,0,1084996,0,"[NULL]","[NULL]"
346          2,"experimental_flamegraph",605908369259172,2,"_ZN7android14AndroidRuntime15javaThreadShellEPv","/system/lib64/libandroid_runtime.so",0,5,0,27704,0,77,0,348050,1,"[NULL]","[NULL]"
347          3,"experimental_flamegraph",605908369259172,3,"_ZN7android6Thread11_threadLoopEPv","/system/lib64/libutils.so",0,5,0,27704,0,77,0,348050,2,"[NULL]","[NULL]"
348          4,"experimental_flamegraph",605908369259172,4,"_ZN7android10PoolThread10threadLoopEv","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,3,"[NULL]","[NULL]"
349          5,"experimental_flamegraph",605908369259172,5,"_ZN7android14IPCThreadState14joinThreadPoolEb","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,4,"[NULL]","[NULL]"
350          6,"experimental_flamegraph",605908369259172,6,"_ZN7android14IPCThreadState20getAndExecuteCommandEv","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,5,"[NULL]","[NULL]"
351          7,"experimental_flamegraph",605908369259172,7,"_ZN7android14IPCThreadState14executeCommandEi","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,6,"[NULL]","[NULL]"
352          8,"experimental_flamegraph",605908369259172,8,"_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,7,"[NULL]","[NULL]"
353          9,"experimental_flamegraph",605908369259172,9,"_ZN11JavaBBinder10onTransactEjRKN7android6ParcelEPS1_j","/system/lib64/libandroid_runtime.so",0,0,0,0,0,60,0,262730,8,"[NULL]","[NULL]"
354        '''))
355
356  def test_heap_profile_tracker_new_stack(self):
357    return DiffTestBlueprint(
358        trace=Path('heap_profile_tracker_new_stack.textproto'),
359        query="""
360        SELECT * FROM heap_profile_allocation;
361        """,
362        out=Csv("""
363        "id","type","ts","upid","heap_name","callsite_id","count","size"
364        0,"heap_profile_allocation",0,0,"unknown",0,1,1
365        1,"heap_profile_allocation",0,0,"unknown",0,-1,-1
366        2,"heap_profile_allocation",1,0,"unknown",0,1,1
367        3,"heap_profile_allocation",1,0,"unknown",0,-1,-1
368        """))
369
370  def test_heap_profile_tracker_twoheaps(self):
371    return DiffTestBlueprint(
372        trace=Path('heap_profile_tracker_twoheaps.textproto'),
373        query="""
374        SELECT * FROM heap_profile_allocation;
375        """,
376        out=Csv("""
377        "id","type","ts","upid","heap_name","callsite_id","count","size"
378        0,"heap_profile_allocation",0,0,"libc.malloc",0,1,1
379        1,"heap_profile_allocation",0,0,"libc.malloc",0,-1,-1
380        2,"heap_profile_allocation",0,0,"custom",0,1,1
381        3,"heap_profile_allocation",0,0,"custom",0,-1,-1
382        """))
383
384  def test_heap_graph_flamegraph_focused(self):
385    return DiffTestBlueprint(
386        trace=Path('heap_graph_branching.textproto'),
387        query="""
388        SELECT
389          id,
390          depth,
391          name,
392          count,
393          cumulative_count,
394          size,
395          cumulative_size,
396          parent_id
397        FROM experimental_flamegraph(
398          'graph',
399          (SELECT max(graph_sample_ts) FROM heap_graph_object),
400          NULL,
401          (SELECT max(upid) FROM heap_graph_object),
402          NULL,
403          'left'
404        )
405        LIMIT 10;
406        """,
407        out=Path('heap_graph_flamegraph_focused.out'))
408
409  def test_heap_graph_superclass(self):
410    return DiffTestBlueprint(
411        trace=Path('heap_graph_superclass.textproto'),
412        query="""
413        SELECT c.id, c.superclass_id, c.name, s.name AS superclass_name, c.location
414        FROM heap_graph_class c LEFT JOIN heap_graph_class s ON c.superclass_id = s.id;
415        """,
416        out=Csv("""
417        "id","superclass_id","name","superclass_name","location"
418        0,"[NULL]","java.lang.Class<java.lang.Object>","[NULL]","l1"
419        1,"[NULL]","java.lang.Class<MySuperClass>","[NULL]","l1"
420        2,"[NULL]","java.lang.Class<MyChildClass>","[NULL]","l2"
421        3,"[NULL]","java.lang.Object","[NULL]","l1"
422        4,3,"MySuperClass","java.lang.Object","l1"
423        5,4,"MyChildClass","MySuperClass","l2"
424        """))
425
426  def test_heap_graph_native_size(self):
427    return DiffTestBlueprint(
428        trace=Path('heap_graph_native_size.textproto'),
429        query="""
430        SELECT c.name AS type_name,
431               o.native_size
432        FROM heap_graph_object o JOIN heap_graph_class c ON o.type_id = c.id
433        WHERE o.root_type = "ROOT_JAVA_FRAME";
434        """,
435        out=Csv("""
436        "type_name","native_size"
437        "android.graphics.Bitmap",123456
438        "android.os.BinderProxy",0
439        """))
440