1// Copyright (C) 2024 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {Duration, Time} from '../../base/time'; 16import { 17 BASE_ROW, 18 BaseSliceTrack, 19 OnSliceClickArgs, 20 OnSliceOverArgs, 21} from '../../components/tracks/base_slice_track'; 22import { 23 ProfileType, 24 profileType, 25 TrackEventDetails, 26 TrackEventSelection, 27} from '../../public/selection'; 28import {Trace} from '../../public/trace'; 29import {Slice} from '../../public/track'; 30import {LONG, STR} from '../../trace_processor/query_result'; 31import {HeapProfileFlamegraphDetailsPanel} from './heap_profile_details_panel'; 32 33const HEAP_PROFILE_ROW = { 34 ...BASE_ROW, 35 type: STR, 36}; 37type HeapProfileRow = typeof HEAP_PROFILE_ROW; 38interface HeapProfileSlice extends Slice { 39 type: ProfileType; 40} 41 42export class HeapProfileTrack extends BaseSliceTrack< 43 HeapProfileSlice, 44 HeapProfileRow 45> { 46 constructor( 47 trace: Trace, 48 uri: string, 49 private readonly tableName: string, 50 private readonly upid: number, 51 private readonly heapProfileIsIncomplete: boolean, 52 ) { 53 super(trace, uri); 54 } 55 56 getSqlSource(): string { 57 return this.tableName; 58 } 59 60 getRowSpec(): HeapProfileRow { 61 return HEAP_PROFILE_ROW; 62 } 63 64 rowToSlice(row: HeapProfileRow): HeapProfileSlice { 65 const slice = this.rowToSliceBase(row); 66 return { 67 ...slice, 68 type: profileType(row.type), 69 }; 70 } 71 72 onSliceOver(args: OnSliceOverArgs<HeapProfileSlice>) { 73 args.tooltip = [args.slice.type]; 74 } 75 76 onSliceClick(args: OnSliceClickArgs<HeapProfileSlice>) { 77 this.trace.selection.selectTrackEvent(this.uri, args.slice.id); 78 } 79 80 async getSelectionDetails( 81 id: number, 82 ): Promise<TrackEventDetails | undefined> { 83 const query = ` 84 SELECT 85 ts, 86 dur, 87 type 88 FROM (${this.getSqlSource()}) 89 WHERE id = ${id} 90 `; 91 92 const result = await this.engine.query(query); 93 if (result.numRows() === 0) { 94 return undefined; 95 } 96 97 const row = result.iter({ 98 ts: LONG, 99 dur: LONG, 100 type: STR, 101 }); 102 103 return { 104 ts: Time.fromRaw(row.ts), 105 dur: Duration.fromRaw(row.dur), 106 profileType: profileType(row.type), 107 }; 108 } 109 110 detailsPanel(sel: TrackEventSelection) { 111 return new HeapProfileFlamegraphDetailsPanel( 112 this.trace, 113 this.heapProfileIsIncomplete, 114 this.upid, 115 sel, 116 ); 117 } 118} 119