xref: /aosp_15_r20/external/perfetto/ui/src/plugins/dev.perfetto.CpuSlices/index.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1// Copyright (C) 2021 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 {CPU_SLICE_TRACK_KIND} from '../../public/track_kinds';
16import {Engine} from '../../trace_processor/engine';
17import {Trace} from '../../public/trace';
18import {PerfettoPlugin} from '../../public/plugin';
19import {NUM, STR_NULL} from '../../trace_processor/query_result';
20import {CpuSliceTrack} from './cpu_slice_track';
21import {TrackNode} from '../../public/workspace';
22import {CpuSliceSelectionAggregator} from './cpu_slice_selection_aggregator';
23import {CpuSliceByProcessSelectionAggregator} from './cpu_slice_by_process_selection_aggregator';
24import ThreadPlugin from '../dev.perfetto.Thread';
25
26function uriForSchedTrack(cpu: number): string {
27  return `/sched_cpu${cpu}`;
28}
29
30export default class implements PerfettoPlugin {
31  static readonly id = 'dev.perfetto.CpuSlices';
32  static readonly dependencies = [ThreadPlugin];
33
34  async onTraceLoad(ctx: Trace): Promise<void> {
35    ctx.selection.registerAreaSelectionAggregator(
36      new CpuSliceSelectionAggregator(),
37    );
38    ctx.selection.registerAreaSelectionAggregator(
39      new CpuSliceByProcessSelectionAggregator(),
40    );
41
42    const cpus = ctx.traceInfo.cpus;
43    const cpuToClusterType = await this.getAndroidCpuClusterTypes(ctx.engine);
44
45    for (const cpu of cpus) {
46      const size = cpuToClusterType.get(cpu);
47      const uri = uriForSchedTrack(cpu);
48
49      const threads = ctx.plugins.getPlugin(ThreadPlugin).getThreadMap();
50
51      const name = size === undefined ? `Cpu ${cpu}` : `Cpu ${cpu} (${size})`;
52      ctx.tracks.registerTrack({
53        uri,
54        title: name,
55        tags: {
56          kind: CPU_SLICE_TRACK_KIND,
57          cpu,
58        },
59        track: new CpuSliceTrack(ctx, uri, cpu, threads),
60      });
61      const trackNode = new TrackNode({uri, title: name, sortOrder: -50});
62      ctx.workspace.addChildInOrder(trackNode);
63    }
64
65    ctx.selection.registerSqlSelectionResolver({
66      sqlTableName: 'sched_slice',
67      callback: async (id: number) => {
68        const result = await ctx.engine.query(`
69          select
70            cpu
71          from sched_slice
72          where id = ${id}
73        `);
74
75        const cpu = result.firstRow({
76          cpu: NUM,
77        }).cpu;
78
79        return {
80          eventId: id,
81          trackUri: uriForSchedTrack(cpu),
82        };
83      },
84    });
85  }
86
87  async getAndroidCpuClusterTypes(
88    engine: Engine,
89  ): Promise<Map<number, string>> {
90    const cpuToClusterType = new Map<number, string>();
91    await engine.query(`
92      include perfetto module android.cpu.cluster_type;
93    `);
94    const result = await engine.query(`
95      select cpu, cluster_type as clusterType
96      from android_cpu_cluster_mapping
97    `);
98
99    const it = result.iter({
100      cpu: NUM,
101      clusterType: STR_NULL,
102    });
103
104    for (; it.valid(); it.next()) {
105      const clusterType = it.clusterType;
106      if (clusterType !== null) {
107        cpuToClusterType.set(it.cpu, clusterType);
108      }
109    }
110
111    return cpuToClusterType;
112  }
113}
114