1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2021 The Android Open Source Project 2*6dbdd20aSAndroid Build Coastguard Worker// 3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*6dbdd20aSAndroid Build Coastguard Worker// 7*6dbdd20aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*6dbdd20aSAndroid Build Coastguard Worker// 9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License. 14*6dbdd20aSAndroid Build Coastguard Worker 15*6dbdd20aSAndroid Build Coastguard Workerimport {CPU_SLICE_TRACK_KIND} from '../../public/track_kinds'; 16*6dbdd20aSAndroid Build Coastguard Workerimport {Engine} from '../../trace_processor/engine'; 17*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace'; 18*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin'; 19*6dbdd20aSAndroid Build Coastguard Workerimport {NUM, STR_NULL} from '../../trace_processor/query_result'; 20*6dbdd20aSAndroid Build Coastguard Workerimport {CpuSliceTrack} from './cpu_slice_track'; 21*6dbdd20aSAndroid Build Coastguard Workerimport {TrackNode} from '../../public/workspace'; 22*6dbdd20aSAndroid Build Coastguard Workerimport {CpuSliceSelectionAggregator} from './cpu_slice_selection_aggregator'; 23*6dbdd20aSAndroid Build Coastguard Workerimport {CpuSliceByProcessSelectionAggregator} from './cpu_slice_by_process_selection_aggregator'; 24*6dbdd20aSAndroid Build Coastguard Workerimport ThreadPlugin from '../dev.perfetto.Thread'; 25*6dbdd20aSAndroid Build Coastguard Worker 26*6dbdd20aSAndroid Build Coastguard Workerfunction uriForSchedTrack(cpu: number): string { 27*6dbdd20aSAndroid Build Coastguard Worker return `/sched_cpu${cpu}`; 28*6dbdd20aSAndroid Build Coastguard Worker} 29*6dbdd20aSAndroid Build Coastguard Worker 30*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin { 31*6dbdd20aSAndroid Build Coastguard Worker static readonly id = 'dev.perfetto.CpuSlices'; 32*6dbdd20aSAndroid Build Coastguard Worker static readonly dependencies = [ThreadPlugin]; 33*6dbdd20aSAndroid Build Coastguard Worker 34*6dbdd20aSAndroid Build Coastguard Worker async onTraceLoad(ctx: Trace): Promise<void> { 35*6dbdd20aSAndroid Build Coastguard Worker ctx.selection.registerAreaSelectionAggregator( 36*6dbdd20aSAndroid Build Coastguard Worker new CpuSliceSelectionAggregator(), 37*6dbdd20aSAndroid Build Coastguard Worker ); 38*6dbdd20aSAndroid Build Coastguard Worker ctx.selection.registerAreaSelectionAggregator( 39*6dbdd20aSAndroid Build Coastguard Worker new CpuSliceByProcessSelectionAggregator(), 40*6dbdd20aSAndroid Build Coastguard Worker ); 41*6dbdd20aSAndroid Build Coastguard Worker 42*6dbdd20aSAndroid Build Coastguard Worker const cpus = ctx.traceInfo.cpus; 43*6dbdd20aSAndroid Build Coastguard Worker const cpuToClusterType = await this.getAndroidCpuClusterTypes(ctx.engine); 44*6dbdd20aSAndroid Build Coastguard Worker 45*6dbdd20aSAndroid Build Coastguard Worker for (const cpu of cpus) { 46*6dbdd20aSAndroid Build Coastguard Worker const size = cpuToClusterType.get(cpu); 47*6dbdd20aSAndroid Build Coastguard Worker const uri = uriForSchedTrack(cpu); 48*6dbdd20aSAndroid Build Coastguard Worker 49*6dbdd20aSAndroid Build Coastguard Worker const threads = ctx.plugins.getPlugin(ThreadPlugin).getThreadMap(); 50*6dbdd20aSAndroid Build Coastguard Worker 51*6dbdd20aSAndroid Build Coastguard Worker const name = size === undefined ? `Cpu ${cpu}` : `Cpu ${cpu} (${size})`; 52*6dbdd20aSAndroid Build Coastguard Worker ctx.tracks.registerTrack({ 53*6dbdd20aSAndroid Build Coastguard Worker uri, 54*6dbdd20aSAndroid Build Coastguard Worker title: name, 55*6dbdd20aSAndroid Build Coastguard Worker tags: { 56*6dbdd20aSAndroid Build Coastguard Worker kind: CPU_SLICE_TRACK_KIND, 57*6dbdd20aSAndroid Build Coastguard Worker cpu, 58*6dbdd20aSAndroid Build Coastguard Worker }, 59*6dbdd20aSAndroid Build Coastguard Worker track: new CpuSliceTrack(ctx, uri, cpu, threads), 60*6dbdd20aSAndroid Build Coastguard Worker }); 61*6dbdd20aSAndroid Build Coastguard Worker const trackNode = new TrackNode({uri, title: name, sortOrder: -50}); 62*6dbdd20aSAndroid Build Coastguard Worker ctx.workspace.addChildInOrder(trackNode); 63*6dbdd20aSAndroid Build Coastguard Worker } 64*6dbdd20aSAndroid Build Coastguard Worker 65*6dbdd20aSAndroid Build Coastguard Worker ctx.selection.registerSqlSelectionResolver({ 66*6dbdd20aSAndroid Build Coastguard Worker sqlTableName: 'sched_slice', 67*6dbdd20aSAndroid Build Coastguard Worker callback: async (id: number) => { 68*6dbdd20aSAndroid Build Coastguard Worker const result = await ctx.engine.query(` 69*6dbdd20aSAndroid Build Coastguard Worker select 70*6dbdd20aSAndroid Build Coastguard Worker cpu 71*6dbdd20aSAndroid Build Coastguard Worker from sched_slice 72*6dbdd20aSAndroid Build Coastguard Worker where id = ${id} 73*6dbdd20aSAndroid Build Coastguard Worker `); 74*6dbdd20aSAndroid Build Coastguard Worker 75*6dbdd20aSAndroid Build Coastguard Worker const cpu = result.firstRow({ 76*6dbdd20aSAndroid Build Coastguard Worker cpu: NUM, 77*6dbdd20aSAndroid Build Coastguard Worker }).cpu; 78*6dbdd20aSAndroid Build Coastguard Worker 79*6dbdd20aSAndroid Build Coastguard Worker return { 80*6dbdd20aSAndroid Build Coastguard Worker eventId: id, 81*6dbdd20aSAndroid Build Coastguard Worker trackUri: uriForSchedTrack(cpu), 82*6dbdd20aSAndroid Build Coastguard Worker }; 83*6dbdd20aSAndroid Build Coastguard Worker }, 84*6dbdd20aSAndroid Build Coastguard Worker }); 85*6dbdd20aSAndroid Build Coastguard Worker } 86*6dbdd20aSAndroid Build Coastguard Worker 87*6dbdd20aSAndroid Build Coastguard Worker async getAndroidCpuClusterTypes( 88*6dbdd20aSAndroid Build Coastguard Worker engine: Engine, 89*6dbdd20aSAndroid Build Coastguard Worker ): Promise<Map<number, string>> { 90*6dbdd20aSAndroid Build Coastguard Worker const cpuToClusterType = new Map<number, string>(); 91*6dbdd20aSAndroid Build Coastguard Worker await engine.query(` 92*6dbdd20aSAndroid Build Coastguard Worker include perfetto module android.cpu.cluster_type; 93*6dbdd20aSAndroid Build Coastguard Worker `); 94*6dbdd20aSAndroid Build Coastguard Worker const result = await engine.query(` 95*6dbdd20aSAndroid Build Coastguard Worker select cpu, cluster_type as clusterType 96*6dbdd20aSAndroid Build Coastguard Worker from android_cpu_cluster_mapping 97*6dbdd20aSAndroid Build Coastguard Worker `); 98*6dbdd20aSAndroid Build Coastguard Worker 99*6dbdd20aSAndroid Build Coastguard Worker const it = result.iter({ 100*6dbdd20aSAndroid Build Coastguard Worker cpu: NUM, 101*6dbdd20aSAndroid Build Coastguard Worker clusterType: STR_NULL, 102*6dbdd20aSAndroid Build Coastguard Worker }); 103*6dbdd20aSAndroid Build Coastguard Worker 104*6dbdd20aSAndroid Build Coastguard Worker for (; it.valid(); it.next()) { 105*6dbdd20aSAndroid Build Coastguard Worker const clusterType = it.clusterType; 106*6dbdd20aSAndroid Build Coastguard Worker if (clusterType !== null) { 107*6dbdd20aSAndroid Build Coastguard Worker cpuToClusterType.set(it.cpu, clusterType); 108*6dbdd20aSAndroid Build Coastguard Worker } 109*6dbdd20aSAndroid Build Coastguard Worker } 110*6dbdd20aSAndroid Build Coastguard Worker 111*6dbdd20aSAndroid Build Coastguard Worker return cpuToClusterType; 112*6dbdd20aSAndroid Build Coastguard Worker } 113*6dbdd20aSAndroid Build Coastguard Worker} 114