xref: /aosp_15_r20/external/perfetto/ui/src/plugins/dev.perfetto.Ftrace/index.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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