Commands and Macros

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.

Running commands

Commands are individual UI actions — pin a track, run a query, create a debug track. Run them through:

Commands support fuzzy matching and autocomplete. See the Commands Automation Reference for the full list of stable commands.

Setting up startup 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.

Pin important tracks automatically

[ { "id": "dev.perfetto.PinTracksByRegex", "args": [".*CPU [0-3].*"] } ]

Create debug tracks for custom metrics

[ { "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)" ] } ]

Use Perfetto SQL modules in debug tracks

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:

Command argument patterns:

Standard analysis setup

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" ] } ]

Creating macros

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"]} ] } ]

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>.

Focus on a specific subsystem

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)" ] } ] } ]

Investigate latency

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)" ] } ] } ]

Combining with trace recording

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"]} ]'

Tips

  1. Startup commands for always-needed views. If you always want certain tracks pinned, use startup commands.

  2. Macros for specific investigations. Create macros for workflows you run occasionally (memory analysis, latency hunting, etc.).

  3. Test interactively first. Use the command palette (Ctrl/Cmd+Shift+P) to try commands before adding them to settings.

  4. Start clean. Begin command sequences with CollapseTracksByRegex using ".*" to collapse all tracks first.

  5. Common regex patterns:

    • Escape dots in package names: "com\\.example\\.app"
    • Match any digit: \\d+
    • Match beginning/end: ^ and $
  6. 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.

Sharing with your team

If you want to share macros and SQL modules with others rather than maintaining them locally, use Extension Servers.

Common issues

See also