xref: /aosp_15_r20/external/perfetto/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1// Copyright (C) 2023 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 {Trace} from '../../public/trace';
16import {PerfettoPlugin} from '../../public/plugin';
17import {addDebugSliceTrack} from '../../components/tracks/debug_tracks';
18import {addQueryResultsTab} from '../../components/query_table/query_result_tab';
19
20const PERF_TRACE_COUNTERS_PRECONDITION = `
21  SELECT
22    str_value
23  FROM metadata
24  WHERE
25    name = 'trace_config_pbtxt'
26    AND str_value GLOB '*ftrace_events: "perf_trace_counters/sched_switch_with_ctrs"*'
27`;
28
29export default class implements PerfettoPlugin {
30  static readonly id = 'dev.perfetto.AndroidPerfTraceCounters';
31  async onTraceLoad(ctx: Trace): Promise<void> {
32    const resp = await ctx.engine.query(PERF_TRACE_COUNTERS_PRECONDITION);
33    if (resp.numRows() === 0) return;
34    ctx.commands.registerCommand({
35      id: 'dev.perfetto.AndroidPerfTraceCounters#ThreadRuntimeIPC',
36      name: 'Add a track to show a thread runtime ipc',
37      callback: async (tid) => {
38        if (tid === undefined) {
39          tid = prompt('Enter a thread tid', '');
40          if (tid === null) return;
41        }
42        const sqlPrefix = `
43          WITH
44            sched_switch_ipc AS (
45              SELECT
46                ts,
47                EXTRACT_ARG(arg_set_id, 'prev_pid') AS tid,
48                EXTRACT_ARG(arg_set_id, 'prev_comm') AS thread_name,
49                EXTRACT_ARG(arg_set_id, 'inst') / (EXTRACT_ARG(arg_set_id, 'cyc') * 1.0) AS ipc,
50                EXTRACT_ARG(arg_set_id, 'inst') AS instruction,
51                EXTRACT_ARG(arg_set_id, 'cyc') AS cycle,
52                EXTRACT_ARG(arg_set_id, 'stallbm') AS stall_backend_mem,
53                EXTRACT_ARG(arg_set_id, 'l3dm') AS l3_cache_miss
54              FROM ftrace_event
55              WHERE name = 'sched_switch_with_ctrs' AND tid = ${tid}
56            ),
57            target_thread_sched_slice AS (
58              SELECT s.*, t.tid, t.name FROM sched s LEFT JOIN thread t USING (utid)
59                WHERE t.tid = ${tid}
60            ),
61            target_thread_ipc_slice AS (
62              SELECT
63                (
64                  SELECT
65                    ts
66                  FROM target_thread_sched_slice ts
67                  WHERE ts.tid = ssi.tid AND ts.ts < ssi.ts
68                  ORDER BY ts.ts DESC
69                  LIMIT 1
70                ) AS ts,
71                (
72                  SELECT
73                    dur
74                  FROM target_thread_sched_slice ts
75                  WHERE ts.tid = ssi.tid AND ts.ts < ssi.ts
76                  ORDER BY ts.ts DESC
77                  LIMIT 1
78                ) AS dur,
79                ssi.ipc,
80                ssi.instruction,
81                ssi.cycle,
82                ssi.stall_backend_mem,
83                ssi.l3_cache_miss
84              FROM sched_switch_ipc ssi
85            )
86        `;
87
88        await addDebugSliceTrack({
89          trace: ctx,
90          data: {
91            sqlSource:
92              sqlPrefix +
93              `
94              SELECT * FROM target_thread_ipc_slice WHERE ts IS NOT NULL`,
95          },
96          title: 'Rutime IPC:' + tid,
97          columns: {ts: 'ts', dur: 'dur', name: 'ipc'},
98          argColumns: [
99            'instruction',
100            'cycle',
101            'stall_backend_mem',
102            'l3_cache_miss',
103          ],
104        });
105        addQueryResultsTab(ctx, {
106          query:
107            sqlPrefix +
108            `
109            SELECT
110              (sum(instruction) * 1.0 / sum(cycle)*1.0) AS avg_ipc,
111              sum(dur)/1e6 as total_runtime_ms,
112              sum(instruction) AS total_instructions,
113              sum(cycle) AS total_cycles,
114              sum(stall_backend_mem) as total_stall_backend_mem,
115              sum(l3_cache_miss) as total_l3_cache_miss
116            FROM target_thread_ipc_slice WHERE ts IS NOT NULL`,
117          title: 'target thread ipc statistic',
118        });
119      },
120    });
121  }
122}
123