This page covers how to automate common Perfetto UI tasks using commands, startup commands, and macros. For an overview of all ways to extend the UI, see Extending the UI.
Commands are individual UI actions — pin a track, run a query, create a debug track. Run them through:
Ctrl+Shift+P (Windows/Linux) or Cmd+Shift+P (Mac)> to transform it into a command paletteCommands support fuzzy matching and autocomplete. See the Commands Automation Reference for the full list of stable commands.
Startup commands run automatically every time you open any trace. Configure them in Settings > Startup Commands.
Startup commands are a JSON array of command objects:
[ {"id": "command.id", "args": ["arg1", "arg2"]} ]
Commands execute in order. These affect only the UI display — the trace file is unchanged.
[ { "id": "dev.perfetto.PinTracksByRegex", "args": [".*CPU [0-3].*"] } ]
[ { "id": "dev.perfetto.AddDebugSliceTrack", "args": [ "SELECT ts, thread.name, dur FROM thread_state JOIN thread USING(utid) WHERE state = 'R' AND dur > 1000000", "Long Scheduling Delays (>1ms)" ] } ]
When your query uses Perfetto modules, include the module first as a separate command:
[ { "id": "dev.perfetto.RunQuery", "args": ["include perfetto module android.screen_state"] }, { "id": "dev.perfetto.AddDebugSliceTrack", "args": [ "SELECT ts, dur FROM android_screen_state WHERE simple_screen_state = 'on'", "Screen On Events" ] } ]
Debug tracks visualize SQL query results on the timeline. The query must return:
ts (timestamp)dur (duration)value (the metric value)Command argument patterns:
AddDebugSliceTrack — [query, title]AddDebugSliceTrackWithPivot — [query, pivot_column, title]This comprehensive startup configuration prepares the UI for system analysis:
[ { "id": "dev.perfetto.CollapseTracksByRegex", "args": [".*"] }, { "id": "dev.perfetto.PinTracksByRegex", "args": [".*CPU \\d+$"] }, { "id": "dev.perfetto.ExpandTracksByRegex", "args": [".*freq.*"] }, { "id": "dev.perfetto.AddDebugSliceTrackWithPivot", "args": [ "SELECT ts, blocked_function as name, dur FROM thread_state WHERE state = 'D' AND blocked_function IS NOT NULL", "name", "Blocking Functions" ] } ]
Macros are named sequences of commands you trigger manually from the command palette. Configure them in Settings > Macros.
Macros are a JSON array of macro objects:
[ { "id": "user.example.MacroName", "name": "Display Name", "run": [ {"id": "command.id", "args": ["arg1"]} ] } ]
user.myteam.MemoryAnalysis). Keep IDs stable — they are used when referencing macros from startup commands.Run macros by typing >name in the command palette (e.g., >Memory Analysis).
Note (Migration): The macros format was changed from a dictionary to an array structure. If you had existing macros, they were automatically migrated to the new format. The migrated macros use IDs in the format
dev.perfetto.UserMacro.<old_name>.
This macro creates a workspace to isolate memory-related tracks:
[ { "id": "user.example.MemoryAnalysis", "name": "Memory Analysis", "run": [ { "id": "dev.perfetto.CreateWorkspace", "args": ["Memory Analysis"] }, { "id": "dev.perfetto.CopyTracksToWorkspaceByRegexWithAncestors", "args": [".*mem.*|.*rss.*", "Memory Analysis"] }, { "id": "dev.perfetto.SwitchWorkspace", "args": ["Memory Analysis"] }, { "id": "dev.perfetto.AddDebugCounterTrackWithPivot", "args": [ "SELECT ts, process.name as process, value FROM counter JOIN process_counter_track ON counter.track_id = process_counter_track.id JOIN process USING (upid) WHERE counter.name = 'mem.rss' AND value > 50000000", "process", "High Memory Processes (>50MB)" ] } ] } ]
This macro helps identify performance bottlenecks:
[ { "id": "user.example.FindLatency", "name": "Find Latency", "run": [ { "id": "dev.perfetto.PinTracksByRegex", "args": [".*CPU.*"] }, { "id": "dev.perfetto.RunQueryAndShowTab", "args": [ "SELECT thread.name, COUNT(*) as blocks, SUM(dur)/1000000 as total_ms FROM thread_state JOIN thread USING(utid) WHERE state = 'D' GROUP BY thread.name ORDER BY total_ms DESC LIMIT 10" ] }, { "id": "dev.perfetto.AddDebugSliceTrackWithPivot", "args": [ "SELECT ts, 'blocked' as name, thread.name as thread_name, dur FROM thread_state JOIN thread USING (utid) WHERE state IN ('R', 'D+') AND dur > 5000000", "thread_name", "Long Waits (>5ms)" ] } ] } ]
When recording traces, specify startup commands that run when the trace opens:
./record_android_trace \ --app com.example.app \ --ui-startup-commands '[ {"id":"dev.perfetto.PinTracksByRegex","args":[".*CPU.*"]}, {"id":"dev.perfetto.AddDebugSliceTrackWithPivot","args":["SELECT ts, thread.name, dur FROM thread_state JOIN thread USING(utid) WHERE state = \"R\"","thread","Runnable Time"]} ]'
Startup commands for always-needed views. If you always want certain tracks pinned, use startup commands.
Macros for specific investigations. Create macros for workflows you run occasionally (memory analysis, latency hunting, etc.).
Test interactively first. Use the command palette (Ctrl/Cmd+Shift+P) to try commands before adding them to settings.
Start clean. Begin command sequences with CollapseTracksByRegex using ".*" to collapse all tracks first.
Common regex patterns:
"com\\.example\\.app"\\d+^ and $Debug tracks need good queries. Ensure SQL returns ts and either dur (for slices) or value (for counters). For Android use cases, see Android Trace Analysis Cookbook.
If you want to share macros and SQL modules with others rather than maintaining them locally, use Extension Servers.
android.screen_state), include the module first with a RunQuery command.