xref: /aosp_15_r20/external/perfetto/ui/src/plugins/dev.perfetto.HeapProfile/heap_profile_track.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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