1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2023 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 m from 'mithril'; 16*6dbdd20aSAndroid Build Coastguard Workerimport {FtraceExplorer, FtraceExplorerCache} from './ftrace_explorer'; 17*6dbdd20aSAndroid Build Coastguard Workerimport {Engine} from '../../trace_processor/engine'; 18*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace'; 19*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin'; 20*6dbdd20aSAndroid Build Coastguard Workerimport {NUM} from '../../trace_processor/query_result'; 21*6dbdd20aSAndroid Build Coastguard Workerimport {FtraceFilter, FtracePluginState} from './common'; 22*6dbdd20aSAndroid Build Coastguard Workerimport {FtraceRawTrack} from './ftrace_track'; 23*6dbdd20aSAndroid Build Coastguard Workerimport {TrackNode} from '../../public/workspace'; 24*6dbdd20aSAndroid Build Coastguard Worker 25*6dbdd20aSAndroid Build Coastguard Workerconst VERSION = 1; 26*6dbdd20aSAndroid Build Coastguard Worker 27*6dbdd20aSAndroid Build Coastguard Workerconst DEFAULT_STATE: FtracePluginState = { 28*6dbdd20aSAndroid Build Coastguard Worker version: VERSION, 29*6dbdd20aSAndroid Build Coastguard Worker filter: { 30*6dbdd20aSAndroid Build Coastguard Worker excludeList: [], 31*6dbdd20aSAndroid Build Coastguard Worker }, 32*6dbdd20aSAndroid Build Coastguard Worker}; 33*6dbdd20aSAndroid Build Coastguard Worker 34*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin { 35*6dbdd20aSAndroid Build Coastguard Worker static readonly id = 'dev.perfetto.Ftrace'; 36*6dbdd20aSAndroid Build Coastguard Worker async onTraceLoad(ctx: Trace): Promise<void> { 37*6dbdd20aSAndroid Build Coastguard Worker const store = ctx.mountStore<FtracePluginState>((init: unknown) => { 38*6dbdd20aSAndroid Build Coastguard Worker if ( 39*6dbdd20aSAndroid Build Coastguard Worker typeof init === 'object' && 40*6dbdd20aSAndroid Build Coastguard Worker init !== null && 41*6dbdd20aSAndroid Build Coastguard Worker 'version' in init && 42*6dbdd20aSAndroid Build Coastguard Worker init.version === VERSION 43*6dbdd20aSAndroid Build Coastguard Worker ) { 44*6dbdd20aSAndroid Build Coastguard Worker return init as {} as FtracePluginState; 45*6dbdd20aSAndroid Build Coastguard Worker } else { 46*6dbdd20aSAndroid Build Coastguard Worker return DEFAULT_STATE; 47*6dbdd20aSAndroid Build Coastguard Worker } 48*6dbdd20aSAndroid Build Coastguard Worker }); 49*6dbdd20aSAndroid Build Coastguard Worker ctx.trash.use(store); 50*6dbdd20aSAndroid Build Coastguard Worker 51*6dbdd20aSAndroid Build Coastguard Worker const filterStore = store.createSubStore( 52*6dbdd20aSAndroid Build Coastguard Worker ['filter'], 53*6dbdd20aSAndroid Build Coastguard Worker (x) => x as FtraceFilter, 54*6dbdd20aSAndroid Build Coastguard Worker ); 55*6dbdd20aSAndroid Build Coastguard Worker ctx.trash.use(filterStore); 56*6dbdd20aSAndroid Build Coastguard Worker 57*6dbdd20aSAndroid Build Coastguard Worker const cpus = await this.lookupCpuCores(ctx.engine); 58*6dbdd20aSAndroid Build Coastguard Worker const group = new TrackNode({ 59*6dbdd20aSAndroid Build Coastguard Worker title: 'Ftrace Events', 60*6dbdd20aSAndroid Build Coastguard Worker sortOrder: -5, 61*6dbdd20aSAndroid Build Coastguard Worker isSummary: true, 62*6dbdd20aSAndroid Build Coastguard Worker }); 63*6dbdd20aSAndroid Build Coastguard Worker 64*6dbdd20aSAndroid Build Coastguard Worker for (const cpuNum of cpus) { 65*6dbdd20aSAndroid Build Coastguard Worker const uri = `/ftrace/cpu${cpuNum}`; 66*6dbdd20aSAndroid Build Coastguard Worker const title = `Ftrace Track for CPU ${cpuNum}`; 67*6dbdd20aSAndroid Build Coastguard Worker 68*6dbdd20aSAndroid Build Coastguard Worker ctx.tracks.registerTrack({ 69*6dbdd20aSAndroid Build Coastguard Worker uri, 70*6dbdd20aSAndroid Build Coastguard Worker title, 71*6dbdd20aSAndroid Build Coastguard Worker tags: { 72*6dbdd20aSAndroid Build Coastguard Worker cpu: cpuNum, 73*6dbdd20aSAndroid Build Coastguard Worker groupName: 'Ftrace Events', 74*6dbdd20aSAndroid Build Coastguard Worker }, 75*6dbdd20aSAndroid Build Coastguard Worker track: new FtraceRawTrack(ctx.engine, cpuNum, filterStore), 76*6dbdd20aSAndroid Build Coastguard Worker }); 77*6dbdd20aSAndroid Build Coastguard Worker 78*6dbdd20aSAndroid Build Coastguard Worker const track = new TrackNode({uri, title}); 79*6dbdd20aSAndroid Build Coastguard Worker group.addChildInOrder(track); 80*6dbdd20aSAndroid Build Coastguard Worker } 81*6dbdd20aSAndroid Build Coastguard Worker 82*6dbdd20aSAndroid Build Coastguard Worker if (group.children.length) { 83*6dbdd20aSAndroid Build Coastguard Worker ctx.workspace.addChildInOrder(group); 84*6dbdd20aSAndroid Build Coastguard Worker } 85*6dbdd20aSAndroid Build Coastguard Worker 86*6dbdd20aSAndroid Build Coastguard Worker const cache: FtraceExplorerCache = { 87*6dbdd20aSAndroid Build Coastguard Worker state: 'blank', 88*6dbdd20aSAndroid Build Coastguard Worker counters: [], 89*6dbdd20aSAndroid Build Coastguard Worker }; 90*6dbdd20aSAndroid Build Coastguard Worker 91*6dbdd20aSAndroid Build Coastguard Worker const ftraceTabUri = 'perfetto.FtraceRaw#FtraceEventsTab'; 92*6dbdd20aSAndroid Build Coastguard Worker 93*6dbdd20aSAndroid Build Coastguard Worker ctx.tabs.registerTab({ 94*6dbdd20aSAndroid Build Coastguard Worker uri: ftraceTabUri, 95*6dbdd20aSAndroid Build Coastguard Worker isEphemeral: false, 96*6dbdd20aSAndroid Build Coastguard Worker content: { 97*6dbdd20aSAndroid Build Coastguard Worker render: () => 98*6dbdd20aSAndroid Build Coastguard Worker m(FtraceExplorer, { 99*6dbdd20aSAndroid Build Coastguard Worker filterStore, 100*6dbdd20aSAndroid Build Coastguard Worker cache, 101*6dbdd20aSAndroid Build Coastguard Worker trace: ctx, 102*6dbdd20aSAndroid Build Coastguard Worker }), 103*6dbdd20aSAndroid Build Coastguard Worker getTitle: () => 'Ftrace Events', 104*6dbdd20aSAndroid Build Coastguard Worker }, 105*6dbdd20aSAndroid Build Coastguard Worker }); 106*6dbdd20aSAndroid Build Coastguard Worker 107*6dbdd20aSAndroid Build Coastguard Worker ctx.commands.registerCommand({ 108*6dbdd20aSAndroid Build Coastguard Worker id: 'perfetto.FtraceRaw#ShowFtraceTab', 109*6dbdd20aSAndroid Build Coastguard Worker name: 'Show ftrace tab', 110*6dbdd20aSAndroid Build Coastguard Worker callback: () => { 111*6dbdd20aSAndroid Build Coastguard Worker ctx.tabs.showTab(ftraceTabUri); 112*6dbdd20aSAndroid Build Coastguard Worker }, 113*6dbdd20aSAndroid Build Coastguard Worker }); 114*6dbdd20aSAndroid Build Coastguard Worker } 115*6dbdd20aSAndroid Build Coastguard Worker 116*6dbdd20aSAndroid Build Coastguard Worker private async lookupCpuCores(engine: Engine): Promise<number[]> { 117*6dbdd20aSAndroid Build Coastguard Worker const query = 'select distinct cpu from ftrace_event order by cpu'; 118*6dbdd20aSAndroid Build Coastguard Worker 119*6dbdd20aSAndroid Build Coastguard Worker const result = await engine.query(query); 120*6dbdd20aSAndroid Build Coastguard Worker const it = result.iter({cpu: NUM}); 121*6dbdd20aSAndroid Build Coastguard Worker 122*6dbdd20aSAndroid Build Coastguard Worker const cpuCores: number[] = []; 123*6dbdd20aSAndroid Build Coastguard Worker 124*6dbdd20aSAndroid Build Coastguard Worker for (; it.valid(); it.next()) { 125*6dbdd20aSAndroid Build Coastguard Worker cpuCores.push(it.cpu); 126*6dbdd20aSAndroid Build Coastguard Worker } 127*6dbdd20aSAndroid Build Coastguard Worker 128*6dbdd20aSAndroid Build Coastguard Worker return cpuCores; 129*6dbdd20aSAndroid Build Coastguard Worker } 130*6dbdd20aSAndroid Build Coastguard Worker} 131