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