1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2024 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 {Trace} from '../../public/trace'; 16*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin'; 17*6dbdd20aSAndroid Build Coastguard Workerimport {TrackNode} from '../../public/workspace'; 18*6dbdd20aSAndroid Build Coastguard Workerimport {NUM, STR, STR_NULL} from '../../trace_processor/query_result'; 19*6dbdd20aSAndroid Build Coastguard Worker 20*6dbdd20aSAndroid Build Coastguard Workerfunction stripPathFromExecutable(path: string) { 21*6dbdd20aSAndroid Build Coastguard Worker if (path[0] === '/') { 22*6dbdd20aSAndroid Build Coastguard Worker return path.split('/').slice(-1)[0]; 23*6dbdd20aSAndroid Build Coastguard Worker } else { 24*6dbdd20aSAndroid Build Coastguard Worker return path; 25*6dbdd20aSAndroid Build Coastguard Worker } 26*6dbdd20aSAndroid Build Coastguard Worker} 27*6dbdd20aSAndroid Build Coastguard Worker 28*6dbdd20aSAndroid Build Coastguard Workerfunction getThreadDisplayName(threadName: string | undefined, tid: number) { 29*6dbdd20aSAndroid Build Coastguard Worker if (threadName) { 30*6dbdd20aSAndroid Build Coastguard Worker return `${stripPathFromExecutable(threadName)} ${tid}`; 31*6dbdd20aSAndroid Build Coastguard Worker } else { 32*6dbdd20aSAndroid Build Coastguard Worker return `Thread ${tid}`; 33*6dbdd20aSAndroid Build Coastguard Worker } 34*6dbdd20aSAndroid Build Coastguard Worker} 35*6dbdd20aSAndroid Build Coastguard Worker 36*6dbdd20aSAndroid Build Coastguard Worker// This plugin is responsible for organizing all process and thread groups 37*6dbdd20aSAndroid Build Coastguard Worker// including the kernel groups, sorting, and adding summary tracks. 38*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin { 39*6dbdd20aSAndroid Build Coastguard Worker static readonly id = 'dev.perfetto.ProcessThreadGroups'; 40*6dbdd20aSAndroid Build Coastguard Worker 41*6dbdd20aSAndroid Build Coastguard Worker private readonly processGroups = new Map<number, TrackNode>(); 42*6dbdd20aSAndroid Build Coastguard Worker private readonly threadGroups = new Map<number, TrackNode>(); 43*6dbdd20aSAndroid Build Coastguard Worker 44*6dbdd20aSAndroid Build Coastguard Worker constructor(private readonly ctx: Trace) {} 45*6dbdd20aSAndroid Build Coastguard Worker 46*6dbdd20aSAndroid Build Coastguard Worker getGroupForProcess(upid: number): TrackNode | undefined { 47*6dbdd20aSAndroid Build Coastguard Worker return this.processGroups.get(upid); 48*6dbdd20aSAndroid Build Coastguard Worker } 49*6dbdd20aSAndroid Build Coastguard Worker 50*6dbdd20aSAndroid Build Coastguard Worker getGroupForThread(utid: number): TrackNode | undefined { 51*6dbdd20aSAndroid Build Coastguard Worker return this.threadGroups.get(utid); 52*6dbdd20aSAndroid Build Coastguard Worker } 53*6dbdd20aSAndroid Build Coastguard Worker 54*6dbdd20aSAndroid Build Coastguard Worker async onTraceLoad(ctx: Trace): Promise<void> { 55*6dbdd20aSAndroid Build Coastguard Worker // Pre-group all kernel "threads" (actually processes) if this is a linux 56*6dbdd20aSAndroid Build Coastguard Worker // system trace. Below, addProcessTrackGroups will skip them due to an 57*6dbdd20aSAndroid Build Coastguard Worker // existing group uuid, and addThreadStateTracks will fill in the 58*6dbdd20aSAndroid Build Coastguard Worker // per-thread tracks. Quirk: since all threads will appear to be 59*6dbdd20aSAndroid Build Coastguard Worker // TrackKindPriority.MAIN_THREAD, any process-level tracks will end up 60*6dbdd20aSAndroid Build Coastguard Worker // pushed to the bottom of the group in the UI. 61*6dbdd20aSAndroid Build Coastguard Worker await this.addKernelThreadGrouping(); 62*6dbdd20aSAndroid Build Coastguard Worker 63*6dbdd20aSAndroid Build Coastguard Worker // Create the per-process track groups. Note that this won't necessarily 64*6dbdd20aSAndroid Build Coastguard Worker // create a track per process. If a process has been completely idle and has 65*6dbdd20aSAndroid Build Coastguard Worker // no sched events, no track group will be emitted. 66*6dbdd20aSAndroid Build Coastguard Worker // Will populate this.addTrackGroupActions 67*6dbdd20aSAndroid Build Coastguard Worker await this.addProcessGroups(); 68*6dbdd20aSAndroid Build Coastguard Worker await this.addThreadGroups(); 69*6dbdd20aSAndroid Build Coastguard Worker 70*6dbdd20aSAndroid Build Coastguard Worker ctx.onTraceReady.addListener(() => { 71*6dbdd20aSAndroid Build Coastguard Worker // If, by the time the trace has finished loading, some of the process or 72*6dbdd20aSAndroid Build Coastguard Worker // thread group tracks nodes have no children, just remove them. 73*6dbdd20aSAndroid Build Coastguard Worker const removeIfEmpty = (g: TrackNode) => { 74*6dbdd20aSAndroid Build Coastguard Worker if (!g.hasChildren) { 75*6dbdd20aSAndroid Build Coastguard Worker g.remove(); 76*6dbdd20aSAndroid Build Coastguard Worker } 77*6dbdd20aSAndroid Build Coastguard Worker }; 78*6dbdd20aSAndroid Build Coastguard Worker this.processGroups.forEach(removeIfEmpty); 79*6dbdd20aSAndroid Build Coastguard Worker this.threadGroups.forEach(removeIfEmpty); 80*6dbdd20aSAndroid Build Coastguard Worker }); 81*6dbdd20aSAndroid Build Coastguard Worker } 82*6dbdd20aSAndroid Build Coastguard Worker 83*6dbdd20aSAndroid Build Coastguard Worker private async addKernelThreadGrouping(): Promise<void> { 84*6dbdd20aSAndroid Build Coastguard Worker // Identify kernel threads if this is a linux system trace, and sufficient 85*6dbdd20aSAndroid Build Coastguard Worker // process information is available. Kernel threads are identified by being 86*6dbdd20aSAndroid Build Coastguard Worker // children of kthreadd (always pid 2). 87*6dbdd20aSAndroid Build Coastguard Worker // The query will return the kthreadd process row first, which must exist 88*6dbdd20aSAndroid Build Coastguard Worker // for any other kthreads to be returned by the query. 89*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): figure out how to handle the idle process (swapper), 90*6dbdd20aSAndroid Build Coastguard Worker // which has pid 0 but appears as a distinct process (with its own comm) on 91*6dbdd20aSAndroid Build Coastguard Worker // each cpu. It'd make sense to exclude its thread state track, but still 92*6dbdd20aSAndroid Build Coastguard Worker // put process-scoped tracks in this group. 93*6dbdd20aSAndroid Build Coastguard Worker const result = await this.ctx.engine.query(` 94*6dbdd20aSAndroid Build Coastguard Worker select 95*6dbdd20aSAndroid Build Coastguard Worker t.utid, p.upid, (case p.pid when 2 then 1 else 0 end) isKthreadd 96*6dbdd20aSAndroid Build Coastguard Worker from 97*6dbdd20aSAndroid Build Coastguard Worker thread t 98*6dbdd20aSAndroid Build Coastguard Worker join process p using (upid) 99*6dbdd20aSAndroid Build Coastguard Worker left join process parent on (p.parent_upid = parent.upid) 100*6dbdd20aSAndroid Build Coastguard Worker join 101*6dbdd20aSAndroid Build Coastguard Worker (select true from metadata m 102*6dbdd20aSAndroid Build Coastguard Worker where (m.name = 'system_name' and m.str_value = 'Linux') 103*6dbdd20aSAndroid Build Coastguard Worker union 104*6dbdd20aSAndroid Build Coastguard Worker select 1 from (select true from sched limit 1)) 105*6dbdd20aSAndroid Build Coastguard Worker where 106*6dbdd20aSAndroid Build Coastguard Worker p.pid = 2 or parent.pid = 2 107*6dbdd20aSAndroid Build Coastguard Worker order by isKthreadd desc 108*6dbdd20aSAndroid Build Coastguard Worker `); 109*6dbdd20aSAndroid Build Coastguard Worker 110*6dbdd20aSAndroid Build Coastguard Worker const it = result.iter({ 111*6dbdd20aSAndroid Build Coastguard Worker utid: NUM, 112*6dbdd20aSAndroid Build Coastguard Worker upid: NUM, 113*6dbdd20aSAndroid Build Coastguard Worker }); 114*6dbdd20aSAndroid Build Coastguard Worker 115*6dbdd20aSAndroid Build Coastguard Worker // Not applying kernel thread grouping. 116*6dbdd20aSAndroid Build Coastguard Worker if (!it.valid()) { 117*6dbdd20aSAndroid Build Coastguard Worker return; 118*6dbdd20aSAndroid Build Coastguard Worker } 119*6dbdd20aSAndroid Build Coastguard Worker 120*6dbdd20aSAndroid Build Coastguard Worker // Create the track group. Use kthreadd's PROCESS_SUMMARY_TRACK for the 121*6dbdd20aSAndroid Build Coastguard Worker // main track. It doesn't summarise the kernel threads within the group, 122*6dbdd20aSAndroid Build Coastguard Worker // but creating a dedicated track type is out of scope at the time of 123*6dbdd20aSAndroid Build Coastguard Worker // writing. 124*6dbdd20aSAndroid Build Coastguard Worker const kernelThreadsGroup = new TrackNode({ 125*6dbdd20aSAndroid Build Coastguard Worker title: 'Kernel threads', 126*6dbdd20aSAndroid Build Coastguard Worker uri: '/kernel', 127*6dbdd20aSAndroid Build Coastguard Worker sortOrder: 50, 128*6dbdd20aSAndroid Build Coastguard Worker isSummary: true, 129*6dbdd20aSAndroid Build Coastguard Worker }); 130*6dbdd20aSAndroid Build Coastguard Worker this.ctx.workspace.addChildInOrder(kernelThreadsGroup); 131*6dbdd20aSAndroid Build Coastguard Worker 132*6dbdd20aSAndroid Build Coastguard Worker // Set the group for all kernel threads (including kthreadd itself). 133*6dbdd20aSAndroid Build Coastguard Worker for (; it.valid(); it.next()) { 134*6dbdd20aSAndroid Build Coastguard Worker const {utid} = it; 135*6dbdd20aSAndroid Build Coastguard Worker 136*6dbdd20aSAndroid Build Coastguard Worker const threadGroup = new TrackNode({ 137*6dbdd20aSAndroid Build Coastguard Worker uri: `thread${utid}`, 138*6dbdd20aSAndroid Build Coastguard Worker title: `Thread ${utid}`, 139*6dbdd20aSAndroid Build Coastguard Worker isSummary: true, 140*6dbdd20aSAndroid Build Coastguard Worker headless: true, 141*6dbdd20aSAndroid Build Coastguard Worker }); 142*6dbdd20aSAndroid Build Coastguard Worker kernelThreadsGroup.addChildInOrder(threadGroup); 143*6dbdd20aSAndroid Build Coastguard Worker this.threadGroups.set(utid, threadGroup); 144*6dbdd20aSAndroid Build Coastguard Worker } 145*6dbdd20aSAndroid Build Coastguard Worker } 146*6dbdd20aSAndroid Build Coastguard Worker 147*6dbdd20aSAndroid Build Coastguard Worker // Adds top level groups for processes and thread that don't belong to a 148*6dbdd20aSAndroid Build Coastguard Worker // process. 149*6dbdd20aSAndroid Build Coastguard Worker private async addProcessGroups(): Promise<void> { 150*6dbdd20aSAndroid Build Coastguard Worker const result = await this.ctx.engine.query(` 151*6dbdd20aSAndroid Build Coastguard Worker with processGroups as ( 152*6dbdd20aSAndroid Build Coastguard Worker select 153*6dbdd20aSAndroid Build Coastguard Worker upid, 154*6dbdd20aSAndroid Build Coastguard Worker process.pid as pid, 155*6dbdd20aSAndroid Build Coastguard Worker process.name as processName, 156*6dbdd20aSAndroid Build Coastguard Worker sum_running_dur as sumRunningDur, 157*6dbdd20aSAndroid Build Coastguard Worker thread_slice_count + process_slice_count as sliceCount, 158*6dbdd20aSAndroid Build Coastguard Worker perf_sample_count as perfSampleCount, 159*6dbdd20aSAndroid Build Coastguard Worker allocation_count as heapProfileAllocationCount, 160*6dbdd20aSAndroid Build Coastguard Worker graph_object_count as heapGraphObjectCount, 161*6dbdd20aSAndroid Build Coastguard Worker ( 162*6dbdd20aSAndroid Build Coastguard Worker select group_concat(string_value) 163*6dbdd20aSAndroid Build Coastguard Worker from args 164*6dbdd20aSAndroid Build Coastguard Worker where 165*6dbdd20aSAndroid Build Coastguard Worker process.arg_set_id is not null and 166*6dbdd20aSAndroid Build Coastguard Worker arg_set_id = process.arg_set_id and 167*6dbdd20aSAndroid Build Coastguard Worker flat_key = 'chrome.process_label' 168*6dbdd20aSAndroid Build Coastguard Worker ) chromeProcessLabels, 169*6dbdd20aSAndroid Build Coastguard Worker case process.name 170*6dbdd20aSAndroid Build Coastguard Worker when 'Browser' then 3 171*6dbdd20aSAndroid Build Coastguard Worker when 'Gpu' then 2 172*6dbdd20aSAndroid Build Coastguard Worker when 'Renderer' then 1 173*6dbdd20aSAndroid Build Coastguard Worker else 0 174*6dbdd20aSAndroid Build Coastguard Worker end as chromeProcessRank 175*6dbdd20aSAndroid Build Coastguard Worker from _process_available_info_summary 176*6dbdd20aSAndroid Build Coastguard Worker join process using(upid) 177*6dbdd20aSAndroid Build Coastguard Worker ), 178*6dbdd20aSAndroid Build Coastguard Worker threadGroups as ( 179*6dbdd20aSAndroid Build Coastguard Worker select 180*6dbdd20aSAndroid Build Coastguard Worker utid, 181*6dbdd20aSAndroid Build Coastguard Worker tid, 182*6dbdd20aSAndroid Build Coastguard Worker thread.name as threadName, 183*6dbdd20aSAndroid Build Coastguard Worker sum_running_dur as sumRunningDur, 184*6dbdd20aSAndroid Build Coastguard Worker slice_count as sliceCount, 185*6dbdd20aSAndroid Build Coastguard Worker perf_sample_count as perfSampleCount 186*6dbdd20aSAndroid Build Coastguard Worker from _thread_available_info_summary 187*6dbdd20aSAndroid Build Coastguard Worker join thread using (utid) 188*6dbdd20aSAndroid Build Coastguard Worker where upid is null 189*6dbdd20aSAndroid Build Coastguard Worker ) 190*6dbdd20aSAndroid Build Coastguard Worker select * 191*6dbdd20aSAndroid Build Coastguard Worker from ( 192*6dbdd20aSAndroid Build Coastguard Worker select 193*6dbdd20aSAndroid Build Coastguard Worker 'process' as kind, 194*6dbdd20aSAndroid Build Coastguard Worker upid as uid, 195*6dbdd20aSAndroid Build Coastguard Worker pid as id, 196*6dbdd20aSAndroid Build Coastguard Worker processName as name 197*6dbdd20aSAndroid Build Coastguard Worker from processGroups 198*6dbdd20aSAndroid Build Coastguard Worker order by 199*6dbdd20aSAndroid Build Coastguard Worker chromeProcessRank desc, 200*6dbdd20aSAndroid Build Coastguard Worker heapProfileAllocationCount desc, 201*6dbdd20aSAndroid Build Coastguard Worker heapGraphObjectCount desc, 202*6dbdd20aSAndroid Build Coastguard Worker perfSampleCount desc, 203*6dbdd20aSAndroid Build Coastguard Worker sumRunningDur desc, 204*6dbdd20aSAndroid Build Coastguard Worker sliceCount desc, 205*6dbdd20aSAndroid Build Coastguard Worker processName asc, 206*6dbdd20aSAndroid Build Coastguard Worker upid asc 207*6dbdd20aSAndroid Build Coastguard Worker ) 208*6dbdd20aSAndroid Build Coastguard Worker union all 209*6dbdd20aSAndroid Build Coastguard Worker select * 210*6dbdd20aSAndroid Build Coastguard Worker from ( 211*6dbdd20aSAndroid Build Coastguard Worker select 212*6dbdd20aSAndroid Build Coastguard Worker 'thread' as kind, 213*6dbdd20aSAndroid Build Coastguard Worker utid as uid, 214*6dbdd20aSAndroid Build Coastguard Worker tid as id, 215*6dbdd20aSAndroid Build Coastguard Worker threadName as name 216*6dbdd20aSAndroid Build Coastguard Worker from threadGroups 217*6dbdd20aSAndroid Build Coastguard Worker order by 218*6dbdd20aSAndroid Build Coastguard Worker perfSampleCount desc, 219*6dbdd20aSAndroid Build Coastguard Worker sumRunningDur desc, 220*6dbdd20aSAndroid Build Coastguard Worker sliceCount desc, 221*6dbdd20aSAndroid Build Coastguard Worker threadName asc, 222*6dbdd20aSAndroid Build Coastguard Worker utid asc 223*6dbdd20aSAndroid Build Coastguard Worker ) 224*6dbdd20aSAndroid Build Coastguard Worker `); 225*6dbdd20aSAndroid Build Coastguard Worker 226*6dbdd20aSAndroid Build Coastguard Worker const it = result.iter({ 227*6dbdd20aSAndroid Build Coastguard Worker kind: STR, 228*6dbdd20aSAndroid Build Coastguard Worker uid: NUM, 229*6dbdd20aSAndroid Build Coastguard Worker id: NUM, 230*6dbdd20aSAndroid Build Coastguard Worker name: STR_NULL, 231*6dbdd20aSAndroid Build Coastguard Worker }); 232*6dbdd20aSAndroid Build Coastguard Worker for (; it.valid(); it.next()) { 233*6dbdd20aSAndroid Build Coastguard Worker const {kind, uid, id, name} = it; 234*6dbdd20aSAndroid Build Coastguard Worker 235*6dbdd20aSAndroid Build Coastguard Worker if (kind === 'process') { 236*6dbdd20aSAndroid Build Coastguard Worker // Ignore kernel process groups 237*6dbdd20aSAndroid Build Coastguard Worker if (this.processGroups.has(uid)) { 238*6dbdd20aSAndroid Build Coastguard Worker continue; 239*6dbdd20aSAndroid Build Coastguard Worker } 240*6dbdd20aSAndroid Build Coastguard Worker 241*6dbdd20aSAndroid Build Coastguard Worker function getProcessDisplayName( 242*6dbdd20aSAndroid Build Coastguard Worker processName: string | undefined, 243*6dbdd20aSAndroid Build Coastguard Worker pid: number, 244*6dbdd20aSAndroid Build Coastguard Worker ) { 245*6dbdd20aSAndroid Build Coastguard Worker if (processName) { 246*6dbdd20aSAndroid Build Coastguard Worker return `${stripPathFromExecutable(processName)} ${pid}`; 247*6dbdd20aSAndroid Build Coastguard Worker } else { 248*6dbdd20aSAndroid Build Coastguard Worker return `Process ${pid}`; 249*6dbdd20aSAndroid Build Coastguard Worker } 250*6dbdd20aSAndroid Build Coastguard Worker } 251*6dbdd20aSAndroid Build Coastguard Worker 252*6dbdd20aSAndroid Build Coastguard Worker const displayName = getProcessDisplayName(name ?? undefined, id); 253*6dbdd20aSAndroid Build Coastguard Worker const group = new TrackNode({ 254*6dbdd20aSAndroid Build Coastguard Worker uri: `/process_${uid}`, 255*6dbdd20aSAndroid Build Coastguard Worker title: displayName, 256*6dbdd20aSAndroid Build Coastguard Worker isSummary: true, 257*6dbdd20aSAndroid Build Coastguard Worker sortOrder: 50, 258*6dbdd20aSAndroid Build Coastguard Worker }); 259*6dbdd20aSAndroid Build Coastguard Worker 260*6dbdd20aSAndroid Build Coastguard Worker // Re-insert the child node to sort it 261*6dbdd20aSAndroid Build Coastguard Worker this.ctx.workspace.addChildInOrder(group); 262*6dbdd20aSAndroid Build Coastguard Worker this.processGroups.set(uid, group); 263*6dbdd20aSAndroid Build Coastguard Worker } else { 264*6dbdd20aSAndroid Build Coastguard Worker // Ignore kernel process groups 265*6dbdd20aSAndroid Build Coastguard Worker if (this.threadGroups.has(uid)) { 266*6dbdd20aSAndroid Build Coastguard Worker continue; 267*6dbdd20aSAndroid Build Coastguard Worker } 268*6dbdd20aSAndroid Build Coastguard Worker 269*6dbdd20aSAndroid Build Coastguard Worker const displayName = getThreadDisplayName(name ?? undefined, id); 270*6dbdd20aSAndroid Build Coastguard Worker const group = new TrackNode({ 271*6dbdd20aSAndroid Build Coastguard Worker uri: `/thread_${uid}`, 272*6dbdd20aSAndroid Build Coastguard Worker title: displayName, 273*6dbdd20aSAndroid Build Coastguard Worker isSummary: true, 274*6dbdd20aSAndroid Build Coastguard Worker sortOrder: 50, 275*6dbdd20aSAndroid Build Coastguard Worker }); 276*6dbdd20aSAndroid Build Coastguard Worker 277*6dbdd20aSAndroid Build Coastguard Worker // Re-insert the child node to sort it 278*6dbdd20aSAndroid Build Coastguard Worker this.ctx.workspace.addChildInOrder(group); 279*6dbdd20aSAndroid Build Coastguard Worker this.threadGroups.set(uid, group); 280*6dbdd20aSAndroid Build Coastguard Worker } 281*6dbdd20aSAndroid Build Coastguard Worker } 282*6dbdd20aSAndroid Build Coastguard Worker } 283*6dbdd20aSAndroid Build Coastguard Worker 284*6dbdd20aSAndroid Build Coastguard Worker // Create all the nested & headless thread groups that live inside existing 285*6dbdd20aSAndroid Build Coastguard Worker // process groups. 286*6dbdd20aSAndroid Build Coastguard Worker private async addThreadGroups(): Promise<void> { 287*6dbdd20aSAndroid Build Coastguard Worker const result = await this.ctx.engine.query(` 288*6dbdd20aSAndroid Build Coastguard Worker with threadGroups as ( 289*6dbdd20aSAndroid Build Coastguard Worker select 290*6dbdd20aSAndroid Build Coastguard Worker utid, 291*6dbdd20aSAndroid Build Coastguard Worker upid, 292*6dbdd20aSAndroid Build Coastguard Worker tid, 293*6dbdd20aSAndroid Build Coastguard Worker thread.name as threadName, 294*6dbdd20aSAndroid Build Coastguard Worker CASE 295*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.is_main_thread = 1 THEN 10 296*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name = 'CrBrowserMain' THEN 10 297*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name = 'CrRendererMain' THEN 10 298*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name = 'CrGpuMain' THEN 10 299*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name glob '*RenderThread*' THEN 9 300*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name glob '*GPU completion*' THEN 8 301*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name = 'Chrome_ChildIOThread' THEN 7 302*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name = 'Chrome_IOThread' THEN 7 303*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name = 'Compositor' THEN 6 304*6dbdd20aSAndroid Build Coastguard Worker WHEN thread.name = 'VizCompositorThread' THEN 6 305*6dbdd20aSAndroid Build Coastguard Worker ELSE 5 306*6dbdd20aSAndroid Build Coastguard Worker END as priority 307*6dbdd20aSAndroid Build Coastguard Worker from _thread_available_info_summary 308*6dbdd20aSAndroid Build Coastguard Worker join thread using (utid) 309*6dbdd20aSAndroid Build Coastguard Worker where upid is not null 310*6dbdd20aSAndroid Build Coastguard Worker ) 311*6dbdd20aSAndroid Build Coastguard Worker select * 312*6dbdd20aSAndroid Build Coastguard Worker from ( 313*6dbdd20aSAndroid Build Coastguard Worker select 314*6dbdd20aSAndroid Build Coastguard Worker utid, 315*6dbdd20aSAndroid Build Coastguard Worker upid, 316*6dbdd20aSAndroid Build Coastguard Worker tid, 317*6dbdd20aSAndroid Build Coastguard Worker threadName 318*6dbdd20aSAndroid Build Coastguard Worker from threadGroups 319*6dbdd20aSAndroid Build Coastguard Worker order by 320*6dbdd20aSAndroid Build Coastguard Worker priority desc, 321*6dbdd20aSAndroid Build Coastguard Worker tid asc 322*6dbdd20aSAndroid Build Coastguard Worker ) 323*6dbdd20aSAndroid Build Coastguard Worker `); 324*6dbdd20aSAndroid Build Coastguard Worker 325*6dbdd20aSAndroid Build Coastguard Worker const it = result.iter({ 326*6dbdd20aSAndroid Build Coastguard Worker utid: NUM, 327*6dbdd20aSAndroid Build Coastguard Worker tid: NUM, 328*6dbdd20aSAndroid Build Coastguard Worker upid: NUM, 329*6dbdd20aSAndroid Build Coastguard Worker threadName: STR_NULL, 330*6dbdd20aSAndroid Build Coastguard Worker }); 331*6dbdd20aSAndroid Build Coastguard Worker for (; it.valid(); it.next()) { 332*6dbdd20aSAndroid Build Coastguard Worker const {utid, tid, upid, threadName} = it; 333*6dbdd20aSAndroid Build Coastguard Worker 334*6dbdd20aSAndroid Build Coastguard Worker // Ignore kernel thread groups 335*6dbdd20aSAndroid Build Coastguard Worker if (this.threadGroups.has(utid)) { 336*6dbdd20aSAndroid Build Coastguard Worker continue; 337*6dbdd20aSAndroid Build Coastguard Worker } 338*6dbdd20aSAndroid Build Coastguard Worker 339*6dbdd20aSAndroid Build Coastguard Worker const group = new TrackNode({ 340*6dbdd20aSAndroid Build Coastguard Worker uri: `/thread_${utid}`, 341*6dbdd20aSAndroid Build Coastguard Worker title: getThreadDisplayName(threadName ?? undefined, tid), 342*6dbdd20aSAndroid Build Coastguard Worker isSummary: true, 343*6dbdd20aSAndroid Build Coastguard Worker headless: true, 344*6dbdd20aSAndroid Build Coastguard Worker }); 345*6dbdd20aSAndroid Build Coastguard Worker this.threadGroups.set(utid, group); 346*6dbdd20aSAndroid Build Coastguard Worker this.processGroups.get(upid)?.addChildInOrder(group); 347*6dbdd20aSAndroid Build Coastguard Worker } 348*6dbdd20aSAndroid Build Coastguard Worker } 349*6dbdd20aSAndroid Build Coastguard Worker} 350