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