diff --git a/ui/src/plugins/com.android.InputEvents/index.ts b/ui/src/plugins/com.android.InputEvents/index.ts index b3f2b35ad5..90aec4da04 100644 --- a/ui/src/plugins/com.android.InputEvents/index.ts +++ b/ui/src/plugins/com.android.InputEvents/index.ts @@ -23,15 +23,6 @@ import {TrackNode} from '../../public/workspace'; import {getOrCreateUserInteractionGroup} from '../../public/standard_groups'; class InputEvents implements PerfettoPlugin { - private readonly SQL_SOURCE = ` - SELECT - read_time as ts, - end_to_end_latency_dur as dur, - CONCAT(event_type, ' ', event_action, ': ', process_name, ' (', input_event_id, ')') as name - FROM android_input_events - WHERE end_to_end_latency_dur IS NOT NULL - `; - async onTraceLoad(ctx: Trace): Promise { const cnt = await ctx.engine.query(` SELECT @@ -43,9 +34,18 @@ class InputEvents implements PerfettoPlugin { return; } + const SQL_SOURCE = ` + SELECT + read_time as ts, + end_to_end_latency_dur as dur, + CONCAT(event_type, ' ', event_action, ': ', process_name, ' (', input_event_id, ')') as name + FROM android_input_events + WHERE end_to_end_latency_dur IS NOT NULL + `; + const config: SimpleSliceTrackConfig = { data: { - sqlSource: this.SQL_SOURCE, + sqlSource: SQL_SOURCE, columns: ['ts', 'dur', 'name'], }, columns: {ts: 'ts', dur: 'dur', name: 'name'}, diff --git a/ui/src/plugins/com.google.android.GoogleCamera/index.ts b/ui/src/plugins/com.google.android.GoogleCamera/index.ts index bd25852d41..4539506641 100644 --- a/ui/src/plugins/com.google.android.GoogleCamera/index.ts +++ b/ui/src/plugins/com.google.android.GoogleCamera/index.ts @@ -17,16 +17,12 @@ import {PerfettoPlugin, PluginDescriptor} from '../../public/plugin'; import * as cameraConstants from './googleCameraConstants'; class GoogleCamera implements PerfettoPlugin { - private ctx!: Trace; - async onTraceLoad(ctx: Trace): Promise { - this.ctx = ctx; - ctx.commands.registerCommand({ id: 'com.google.android.GoogleCamera#LoadGoogleCameraStartupView', name: 'Load google camera startup view', callback: () => { - this.loadGCAStartupView(); + this.loadGCAStartupView(ctx); }, }); @@ -43,18 +39,18 @@ class GoogleCamera implements PerfettoPlugin { ) { return item.trim(); }); - this.pinTracks(trackNameList); + this.pinTracks(ctx, trackNameList); }, }); } - private loadGCAStartupView() { - this.pinTracks(cameraConstants.MAIN_THREAD_TRACK); - this.pinTracks(cameraConstants.STARTUP_RELATED_TRACKS); + private loadGCAStartupView(ctx: Trace) { + this.pinTracks(ctx, cameraConstants.MAIN_THREAD_TRACK); + this.pinTracks(ctx, cameraConstants.STARTUP_RELATED_TRACKS); } - private pinTracks(trackNames: ReadonlyArray) { - this.ctx.workspace.flatTracks.forEach((track) => { + private pinTracks(ctx: Trace, trackNames: ReadonlyArray) { + ctx.workspace.flatTracks.forEach((track) => { trackNames.forEach((trackName) => { if (track.title.match(trackName)) { track.pin(); diff --git a/ui/src/plugins/dev.perfetto.AsyncSlices/index.ts b/ui/src/plugins/dev.perfetto.AsyncSlices/index.ts index 4888c55999..b27991c6a5 100644 --- a/ui/src/plugins/dev.perfetto.AsyncSlices/index.ts +++ b/ui/src/plugins/dev.perfetto.AsyncSlices/index.ts @@ -32,14 +32,12 @@ import {getSliceTable} from './table'; import {extensions} from '../../public/lib/extensions'; class AsyncSlicePlugin implements PerfettoPlugin { - private readonly trackIdsToUris = new Map(); - async onTraceLoad(ctx: Trace): Promise { - this.trackIdsToUris.clear(); + const trackIdsToUris = new Map(); - await this.addGlobalAsyncTracks(ctx); - await this.addProcessAsyncSliceTracks(ctx); - await this.addThreadAsyncSliceTracks(ctx); + await this.addGlobalAsyncTracks(ctx, trackIdsToUris); + await this.addProcessAsyncSliceTracks(ctx, trackIdsToUris); + await this.addThreadAsyncSliceTracks(ctx, trackIdsToUris); ctx.selection.registerSqlSelectionResolver({ sqlTableName: 'slice', @@ -61,7 +59,7 @@ class AsyncSlicePlugin implements PerfettoPlugin { trackId: NUM, }); - const trackUri = this.trackIdsToUris.get(trackId); + const trackUri = trackIdsToUris.get(trackId); if (!trackUri) { return undefined; } @@ -90,7 +88,10 @@ class AsyncSlicePlugin implements PerfettoPlugin { }); } - async addGlobalAsyncTracks(ctx: Trace): Promise { + async addGlobalAsyncTracks( + ctx: Trace, + trackIdsToUris: Map, + ): Promise { const {engine} = ctx; // TODO(stevegolton): The track exclusion logic is currently a hack. This will be replaced // by a mechanism for more specific plugins to override tracks from more generic plugins. @@ -204,7 +205,7 @@ class AsyncSlicePlugin implements PerfettoPlugin { }); trackIds.forEach((id) => { trackMap.set(id, {parentId: it.parentId, trackNode}); - this.trackIdsToUris.set(id, uri); + trackIdsToUris.set(id, uri); }); } } @@ -220,7 +221,10 @@ class AsyncSlicePlugin implements PerfettoPlugin { }); } - async addProcessAsyncSliceTracks(ctx: Trace): Promise { + async addProcessAsyncSliceTracks( + ctx: Trace, + trackIdsToUris: Map, + ): Promise { const result = await ctx.engine.query(` select upid, @@ -283,7 +287,7 @@ class AsyncSlicePlugin implements PerfettoPlugin { const track = new TrackNode({uri, title, sortOrder: 30}); trackIds.forEach((id) => { trackMap.set(id, {trackNode: track, parentId: it.parentId, upid}); - this.trackIdsToUris.set(id, uri); + trackIdsToUris.set(id, uri); }); } @@ -299,7 +303,10 @@ class AsyncSlicePlugin implements PerfettoPlugin { }); } - async addThreadAsyncSliceTracks(ctx: Trace): Promise { + async addThreadAsyncSliceTracks( + ctx: Trace, + trackIdsToUris: Map, + ): Promise { const result = await ctx.engine.query(` include perfetto module viz.summary.slices; include perfetto module viz.summary.threads; @@ -381,7 +388,7 @@ class AsyncSlicePlugin implements PerfettoPlugin { const track = new TrackNode({uri, title, sortOrder: 20}); trackIds.forEach((id) => { trackMap.set(id, {trackNode: track, parentId, utid}); - this.trackIdsToUris.set(id, uri); + trackIdsToUris.set(id, uri); }); } diff --git a/ui/src/plugins/dev.perfetto.ProcessThreadGroups/index.ts b/ui/src/plugins/dev.perfetto.ProcessThreadGroups/index.ts index 101816ae65..a4d09dde08 100644 --- a/ui/src/plugins/dev.perfetto.ProcessThreadGroups/index.ts +++ b/ui/src/plugins/dev.perfetto.ProcessThreadGroups/index.ts @@ -40,16 +40,9 @@ function getThreadDisplayName(threadName: string | undefined, tid: number) { // This plugin is responsible for organizing all process and thread groups // including the kernel groups, sorting, and adding summary tracks. class ProcessThreadGroupsPlugin implements PerfettoPlugin { - private readonly processGroups = new Map(); - private readonly threadGroups = new Map(); - async onTraceLoad(ctx: Trace): Promise { - await this.addProcessAndThreadGroups(ctx); - } - - private async addProcessAndThreadGroups(ctx: Trace): Promise { - this.processGroups.clear(); - this.threadGroups.clear(); + const processGroups = new Map(); + const threadGroups = new Map(); // Pre-group all kernel "threads" (actually processes) if this is a linux // system trace. Below, addProcessTrackGroups will skip them due to an @@ -57,14 +50,14 @@ class ProcessThreadGroupsPlugin implements PerfettoPlugin { // per-thread tracks. Quirk: since all threads will appear to be // TrackKindPriority.MAIN_THREAD, any process-level tracks will end up // pushed to the bottom of the group in the UI. - await this.addKernelThreadGrouping(ctx); + await this.addKernelThreadGrouping(ctx, threadGroups); // Create the per-process track groups. Note that this won't necessarily // create a track per process. If a process has been completely idle and has // no sched events, no track group will be emitted. // Will populate this.addTrackGroupActions - await this.addProcessGroups(ctx); - await this.addThreadGroups(ctx); + await this.addProcessGroups(ctx, processGroups, threadGroups); + await this.addThreadGroups(ctx, processGroups, threadGroups); ctx.addEventListener('traceready', () => { // If, by the time the trace has finished loading, some of the process or @@ -74,12 +67,15 @@ class ProcessThreadGroupsPlugin implements PerfettoPlugin { g.remove(); } }; - this.processGroups.forEach(removeIfEmpty); - this.threadGroups.forEach(removeIfEmpty); + processGroups.forEach(removeIfEmpty); + threadGroups.forEach(removeIfEmpty); }); } - private async addKernelThreadGrouping(ctx: Trace): Promise { + private async addKernelThreadGrouping( + ctx: Trace, + threadGroups: Map, + ): Promise { // Identify kernel threads if this is a linux system trace, and sufficient // process information is available. Kernel threads are identified by being // children of kthreadd (always pid 2). @@ -136,13 +132,17 @@ class ProcessThreadGroupsPlugin implements PerfettoPlugin { threadGroup.headless = true; kernelThreadsGroup.addChildInOrder(threadGroup); - this.threadGroups.set(utid, threadGroup); + threadGroups.set(utid, threadGroup); } } // Adds top level groups for processes and thread that don't belong to a // process. - private async addProcessGroups(ctx: Trace): Promise { + private async addProcessGroups( + ctx: Trace, + processGroups: Map, + threadGroups: Map, + ): Promise { const result = await ctx.engine.query(` with processGroups as ( select @@ -230,7 +230,7 @@ class ProcessThreadGroupsPlugin implements PerfettoPlugin { if (kind === 'process') { // Ignore kernel process groups - if (this.processGroups.has(uid)) { + if (processGroups.has(uid)) { continue; } @@ -253,10 +253,10 @@ class ProcessThreadGroupsPlugin implements PerfettoPlugin { // Re-insert the child node to sort it ctx.workspace.addChildInOrder(group); - this.processGroups.set(uid, group); + processGroups.set(uid, group); } else { // Ignore kernel process groups - if (this.threadGroups.has(uid)) { + if (threadGroups.has(uid)) { continue; } @@ -268,14 +268,18 @@ class ProcessThreadGroupsPlugin implements PerfettoPlugin { // Re-insert the child node to sort it ctx.workspace.addChildInOrder(group); - this.threadGroups.set(uid, group); + threadGroups.set(uid, group); } } } // Create all the nested & headless thread groups that live inside existing // process groups. - private async addThreadGroups(ctx: Trace): Promise { + private async addThreadGroups( + ctx: Trace, + processGroups: Map, + threadGroups: Map, + ): Promise { const result = await ctx.engine.query(` with threadGroups as ( select @@ -324,15 +328,15 @@ class ProcessThreadGroupsPlugin implements PerfettoPlugin { const {utid, tid, upid, threadName} = it; // Ignore kernel thread groups - if (this.threadGroups.has(utid)) { + if (threadGroups.has(utid)) { continue; } const group = getOrCreateGroupForThread(ctx.workspace, utid); group.title = getThreadDisplayName(threadName ?? undefined, tid); - this.threadGroups.set(utid, group); + threadGroups.set(utid, group); group.headless = true; - this.processGroups.get(upid)?.addChildInOrder(group); + processGroups.get(upid)?.addChildInOrder(group); } } }