• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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';
25import {createAggregationToTabAdaptor} from '../../components/aggregation_adapter';
26
27function uriForSchedTrack(cpu: number): string {
28  return `/sched_cpu${cpu}`;
29}
30
31export default class implements PerfettoPlugin {
32  static readonly id = 'dev.perfetto.CpuSlices';
33  static readonly dependencies = [ThreadPlugin];
34
35  async onTraceLoad(ctx: Trace): Promise<void> {
36    ctx.selection.registerAreaSelectionTab(
37      createAggregationToTabAdaptor(ctx, new CpuSliceSelectionAggregator()),
38    );
39    ctx.selection.registerAreaSelectionTab(
40      createAggregationToTabAdaptor(
41        ctx,
42        new CpuSliceByProcessSelectionAggregator(),
43      ),
44    );
45
46    // ctx.traceInfo.cpus contains all cpus seen from all events. Filter the set
47    // if it's seen in sched slices.
48    const queryRes = await ctx.engine.query(
49      `select distinct ucpu from sched order by ucpu;`,
50    );
51    const ucpus = new Set<number>();
52    for (const it = queryRes.iter({ucpu: NUM}); it.valid(); it.next()) {
53      ucpus.add(it.ucpu);
54    }
55    const cpus = ctx.traceInfo.cpus.filter((cpu) => ucpus.has(cpu.ucpu));
56    const cpuToClusterType = await this.getAndroidCpuClusterTypes(ctx.engine);
57
58    for (const cpu of cpus) {
59      const uri = uriForSchedTrack(cpu.ucpu);
60      const size = cpuToClusterType.get(cpu.cpu);
61      const sizeStr = size === undefined ? `` : ` (${size})`;
62      const name = `Cpu ${cpu.cpu}${sizeStr}${cpu.maybeMachineLabel()}`;
63
64      const threads = ctx.plugins.getPlugin(ThreadPlugin).getThreadMap();
65
66      ctx.tracks.registerTrack({
67        uri,
68        title: name,
69        tags: {
70          kind: CPU_SLICE_TRACK_KIND,
71          cpu: cpu.ucpu,
72        },
73        track: new CpuSliceTrack(ctx, uri, cpu, threads),
74      });
75      const trackNode = new TrackNode({uri, title: name, sortOrder: -50});
76      ctx.workspace.addChildInOrder(trackNode);
77    }
78  }
79
80  async getAndroidCpuClusterTypes(
81    engine: Engine,
82  ): Promise<Map<number, string>> {
83    const cpuToClusterType = new Map<number, string>();
84    await engine.query(`
85      include perfetto module android.cpu.cluster_type;
86    `);
87    const result = await engine.query(`
88      select cpu, cluster_type as clusterType
89      from android_cpu_cluster_mapping
90    `);
91
92    const it = result.iter({
93      cpu: NUM,
94      clusterType: STR_NULL,
95    });
96
97    for (; it.valid(); it.next()) {
98      const clusterType = it.clusterType;
99      if (clusterType !== null) {
100        cpuToClusterType.set(it.cpu, clusterType);
101      }
102    }
103
104    return cpuToClusterType;
105  }
106}
107