• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2023 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 {
16  NUM_NULL,
17  Plugin,
18  PluginContextTrace,
19  PluginDescriptor,
20  STR_NULL,
21} from '../../public';
22import {NamedSliceTrack} from '../../frontend/named_slice_track';
23import {NewTrackArgs} from '../../frontend/track';
24
25class GpuPidTrack extends NamedSliceTrack {
26  upid: number;
27
28  constructor(args: NewTrackArgs, upid: number) {
29    super(args);
30    this.upid = upid;
31  }
32
33  getSqlSource(): string {
34    return `
35      SELECT *
36      FROM gpu_slice
37      WHERE upid = ${this.upid}
38    `;
39  }
40}
41
42class GpuByProcess implements Plugin {
43  async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
44    // Find all unique upid values in gpu_slices and join with process table.
45    const results = await ctx.engine.query(`
46      WITH slice_upids AS (
47        SELECT DISTINCT upid FROM gpu_slice
48      )
49      SELECT upid, pid, name FROM slice_upids JOIN process USING (upid)
50    `);
51
52    const it = results.iter({
53      upid: NUM_NULL,
54      pid: NUM_NULL,
55      name: STR_NULL,
56    });
57
58    // For each upid, create a GpuPidTrack.
59    for (; it.valid(); it.next()) {
60      if (it.upid == null) {
61        continue;
62      }
63
64      const upid = it.upid;
65      let processName = 'Unknown';
66      if (it.name != null) {
67        processName = it.name;
68      } else if (it.pid != null) {
69        processName = `${it.pid}`;
70      }
71
72      ctx.registerStaticTrack({
73        uri: `dev.perfetto.GpuByProcess#${upid}`,
74        displayName: `GPU ${processName}`,
75        trackFactory: ({trackKey}) => {
76          return new GpuPidTrack({engine: ctx.engine, trackKey}, upid);
77        },
78      });
79    }
80  }
81
82  async onTraceUnload(_: PluginContextTrace): Promise<void> {}
83}
84
85export const plugin: PluginDescriptor = {
86  pluginId: 'dev.perfetto.GpuByProcess',
87  plugin: GpuByProcess,
88};
89