xref: /aosp_15_r20/external/perfetto/ui/src/plugins/dev.perfetto.HeapProfile/index.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2021 The Android Open Source Project
2*6dbdd20aSAndroid Build Coastguard Worker//
3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*6dbdd20aSAndroid Build Coastguard Worker//
7*6dbdd20aSAndroid Build Coastguard Worker//      http://www.apache.org/licenses/LICENSE-2.0
8*6dbdd20aSAndroid Build Coastguard Worker//
9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License.
14*6dbdd20aSAndroid Build Coastguard Worker
15*6dbdd20aSAndroid Build Coastguard Workerimport {HEAP_PROFILE_TRACK_KIND} from '../../public/track_kinds';
16*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace';
17*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin';
18*6dbdd20aSAndroid Build Coastguard Workerimport {LONG, NUM, STR} from '../../trace_processor/query_result';
19*6dbdd20aSAndroid Build Coastguard Workerimport {HeapProfileTrack} from './heap_profile_track';
20*6dbdd20aSAndroid Build Coastguard Workerimport {TrackNode} from '../../public/workspace';
21*6dbdd20aSAndroid Build Coastguard Workerimport {createPerfettoTable} from '../../trace_processor/sql_utils';
22*6dbdd20aSAndroid Build Coastguard Workerimport ProcessThreadGroupsPlugin from '../dev.perfetto.ProcessThreadGroups';
23*6dbdd20aSAndroid Build Coastguard Worker
24*6dbdd20aSAndroid Build Coastguard Workerfunction getUriForTrack(upid: number): string {
25*6dbdd20aSAndroid Build Coastguard Worker  return `/process_${upid}/heap_profile`;
26*6dbdd20aSAndroid Build Coastguard Worker}
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin {
29*6dbdd20aSAndroid Build Coastguard Worker  static readonly id = 'dev.perfetto.HeapProfile';
30*6dbdd20aSAndroid Build Coastguard Worker  static readonly dependencies = [ProcessThreadGroupsPlugin];
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Worker  async onTraceLoad(ctx: Trace): Promise<void> {
33*6dbdd20aSAndroid Build Coastguard Worker    const it = await ctx.engine.query(`
34*6dbdd20aSAndroid Build Coastguard Worker      select value from stats
35*6dbdd20aSAndroid Build Coastguard Worker      where name = 'heap_graph_non_finalized_graph'
36*6dbdd20aSAndroid Build Coastguard Worker    `);
37*6dbdd20aSAndroid Build Coastguard Worker    const incomplete = it.firstRow({value: NUM}).value > 0;
38*6dbdd20aSAndroid Build Coastguard Worker
39*6dbdd20aSAndroid Build Coastguard Worker    const result = await ctx.engine.query(`
40*6dbdd20aSAndroid Build Coastguard Worker      select distinct upid from heap_profile_allocation
41*6dbdd20aSAndroid Build Coastguard Worker      union
42*6dbdd20aSAndroid Build Coastguard Worker      select distinct upid from heap_graph_object
43*6dbdd20aSAndroid Build Coastguard Worker    `);
44*6dbdd20aSAndroid Build Coastguard Worker    for (const it = result.iter({upid: NUM}); it.valid(); it.next()) {
45*6dbdd20aSAndroid Build Coastguard Worker      const upid = it.upid;
46*6dbdd20aSAndroid Build Coastguard Worker      const uri = getUriForTrack(upid);
47*6dbdd20aSAndroid Build Coastguard Worker      const title = 'Heap Profile';
48*6dbdd20aSAndroid Build Coastguard Worker      const tableName = `_heap_profile_${upid}`;
49*6dbdd20aSAndroid Build Coastguard Worker
50*6dbdd20aSAndroid Build Coastguard Worker      createPerfettoTable(
51*6dbdd20aSAndroid Build Coastguard Worker        ctx.engine,
52*6dbdd20aSAndroid Build Coastguard Worker        tableName,
53*6dbdd20aSAndroid Build Coastguard Worker        `
54*6dbdd20aSAndroid Build Coastguard Worker          with
55*6dbdd20aSAndroid Build Coastguard Worker            heaps as (select group_concat(distinct heap_name) h from heap_profile_allocation where upid = ${upid}),
56*6dbdd20aSAndroid Build Coastguard Worker            allocation_tses as (select distinct ts from heap_profile_allocation where upid = ${upid}),
57*6dbdd20aSAndroid Build Coastguard Worker            graph_tses as (select distinct graph_sample_ts from heap_graph_object where upid = ${upid})
58*6dbdd20aSAndroid Build Coastguard Worker          select
59*6dbdd20aSAndroid Build Coastguard Worker            *,
60*6dbdd20aSAndroid Build Coastguard Worker            0 AS dur,
61*6dbdd20aSAndroid Build Coastguard Worker            0 AS depth
62*6dbdd20aSAndroid Build Coastguard Worker          from (
63*6dbdd20aSAndroid Build Coastguard Worker            select
64*6dbdd20aSAndroid Build Coastguard Worker              (
65*6dbdd20aSAndroid Build Coastguard Worker                select a.id
66*6dbdd20aSAndroid Build Coastguard Worker                from heap_profile_allocation a
67*6dbdd20aSAndroid Build Coastguard Worker                where a.ts = t.ts
68*6dbdd20aSAndroid Build Coastguard Worker                order by a.id
69*6dbdd20aSAndroid Build Coastguard Worker                limit 1
70*6dbdd20aSAndroid Build Coastguard Worker              ) as id,
71*6dbdd20aSAndroid Build Coastguard Worker              ts,
72*6dbdd20aSAndroid Build Coastguard Worker              'heap_profile:' || (select h from heaps) AS type
73*6dbdd20aSAndroid Build Coastguard Worker            from allocation_tses t
74*6dbdd20aSAndroid Build Coastguard Worker            union all
75*6dbdd20aSAndroid Build Coastguard Worker            select
76*6dbdd20aSAndroid Build Coastguard Worker              (
77*6dbdd20aSAndroid Build Coastguard Worker                select o.id
78*6dbdd20aSAndroid Build Coastguard Worker                from heap_graph_object o
79*6dbdd20aSAndroid Build Coastguard Worker                where o.graph_sample_ts = g.graph_sample_ts
80*6dbdd20aSAndroid Build Coastguard Worker                order by o.id
81*6dbdd20aSAndroid Build Coastguard Worker                limit 1
82*6dbdd20aSAndroid Build Coastguard Worker              ) as id,
83*6dbdd20aSAndroid Build Coastguard Worker              graph_sample_ts AS ts,
84*6dbdd20aSAndroid Build Coastguard Worker              'graph' AS type
85*6dbdd20aSAndroid Build Coastguard Worker            from graph_tses g
86*6dbdd20aSAndroid Build Coastguard Worker          )
87*6dbdd20aSAndroid Build Coastguard Worker        `,
88*6dbdd20aSAndroid Build Coastguard Worker      );
89*6dbdd20aSAndroid Build Coastguard Worker
90*6dbdd20aSAndroid Build Coastguard Worker      ctx.tracks.registerTrack({
91*6dbdd20aSAndroid Build Coastguard Worker        uri,
92*6dbdd20aSAndroid Build Coastguard Worker        title,
93*6dbdd20aSAndroid Build Coastguard Worker        tags: {
94*6dbdd20aSAndroid Build Coastguard Worker          kind: HEAP_PROFILE_TRACK_KIND,
95*6dbdd20aSAndroid Build Coastguard Worker          upid,
96*6dbdd20aSAndroid Build Coastguard Worker        },
97*6dbdd20aSAndroid Build Coastguard Worker        track: new HeapProfileTrack(ctx, uri, tableName, upid, incomplete),
98*6dbdd20aSAndroid Build Coastguard Worker      });
99*6dbdd20aSAndroid Build Coastguard Worker      const group = ctx.plugins
100*6dbdd20aSAndroid Build Coastguard Worker        .getPlugin(ProcessThreadGroupsPlugin)
101*6dbdd20aSAndroid Build Coastguard Worker        .getGroupForProcess(upid);
102*6dbdd20aSAndroid Build Coastguard Worker      const track = new TrackNode({uri, title, sortOrder: -30});
103*6dbdd20aSAndroid Build Coastguard Worker      group?.addChildInOrder(track);
104*6dbdd20aSAndroid Build Coastguard Worker    }
105*6dbdd20aSAndroid Build Coastguard Worker
106*6dbdd20aSAndroid Build Coastguard Worker    ctx.onTraceReady.addListener(async () => {
107*6dbdd20aSAndroid Build Coastguard Worker      await selectFirstHeapProfile(ctx);
108*6dbdd20aSAndroid Build Coastguard Worker    });
109*6dbdd20aSAndroid Build Coastguard Worker  }
110*6dbdd20aSAndroid Build Coastguard Worker}
111*6dbdd20aSAndroid Build Coastguard Worker
112*6dbdd20aSAndroid Build Coastguard Workerasync function selectFirstHeapProfile(ctx: Trace) {
113*6dbdd20aSAndroid Build Coastguard Worker  const query = `
114*6dbdd20aSAndroid Build Coastguard Worker    select * from (
115*6dbdd20aSAndroid Build Coastguard Worker      select
116*6dbdd20aSAndroid Build Coastguard Worker        min(ts) AS ts,
117*6dbdd20aSAndroid Build Coastguard Worker        'heap_profile:' || group_concat(distinct heap_name) AS type,
118*6dbdd20aSAndroid Build Coastguard Worker        upid
119*6dbdd20aSAndroid Build Coastguard Worker      from heap_profile_allocation
120*6dbdd20aSAndroid Build Coastguard Worker      group by upid
121*6dbdd20aSAndroid Build Coastguard Worker      union
122*6dbdd20aSAndroid Build Coastguard Worker      select distinct graph_sample_ts as ts, 'graph' as type, upid
123*6dbdd20aSAndroid Build Coastguard Worker      from heap_graph_object
124*6dbdd20aSAndroid Build Coastguard Worker    )
125*6dbdd20aSAndroid Build Coastguard Worker    order by ts
126*6dbdd20aSAndroid Build Coastguard Worker    limit 1
127*6dbdd20aSAndroid Build Coastguard Worker  `;
128*6dbdd20aSAndroid Build Coastguard Worker  const profile = await ctx.engine.query(query);
129*6dbdd20aSAndroid Build Coastguard Worker  if (profile.numRows() !== 1) return;
130*6dbdd20aSAndroid Build Coastguard Worker  const row = profile.firstRow({ts: LONG, type: STR, upid: NUM});
131*6dbdd20aSAndroid Build Coastguard Worker  const upid = row.upid;
132*6dbdd20aSAndroid Build Coastguard Worker
133*6dbdd20aSAndroid Build Coastguard Worker  ctx.selection.selectTrackEvent(getUriForTrack(upid), 0);
134*6dbdd20aSAndroid Build Coastguard Worker}
135