Profile and debug performance
Updated: Aug 28, 2026
Meta VR CLI (metavr) captures Perfetto traces from a headset and analyzes them on your machine. It also samples the CPU with simpleperf and pulls memory snapshots off the device. This guide covers the capture and analyze loop, then the other profiling tools.
- Meta VR CLI installed. See Install Meta VR CLI.
- Developer Mode on, USB debugging authorized, and a connected headset.
- The
perfetto binary on the headset. Capture fails without it.
Note: Analysis needs Perfetto’s trace processor on your machine. metavr downloads it the first time you run an analysis command, so there is no manual step. That first command pauses while it downloads. To get it ahead of time, run metavr tools install perfetto.
Your headset appears in the list. If it does not, fix that before you capture.
metavr perf capture --app com.example.myapp --mode vr --duration 10000
--duration is in milliseconds and defaults to 5000. --mode takes a preset: standard (the default), gpu, cpu, memory, lightweight, full, vr, or custom. Add --launch to force-stop the app first, so a cold start lands inside the trace.
The command prints the file path, the size, and a session ID. Every analysis command takes that session ID.
To name the trace file yourself, pass --output (short form -o) with a name and no extension:
metavr perf capture --app com.example.myapp --output before-fix
Note: Re-using an --output name overwrites the earlier trace.
To control the capture window yourself, run it in two parts:
metavr perf start --app com.example.myapp --mode vr
metavr perf stop <PID> <OUTPUT_NAME>
perf start prints the PID and the output name. perf stop needs both.
metavr perf analyze-trace
Omit the session ID and it uses your newest trace. Narrow the report with --focus, which takes overview (the default), gpu, cpu, frames, or threads.
Note: You do not need to load a trace first. Every analysis command loads it for you. metavr perf load exists only as a quick check that a trace parses.
To see what you have captured:
Newest first. -l/--limit <N> defaults to 10.
Run SQL against the trace:
metavr perf query <SESSION_ID> "SELECT * FROM thread LIMIT 10"
The query returns both a tid and a utid column. Take the utid and look at how that thread spent its time:
metavr perf thread-state <SESSION_ID> <UTID>
You get running, runnable, and sleeping time, covering up to 100 state changes.
For GPU counters, pass matching lists of frame start and end times in nanoseconds:
metavr perf gpu-counters <SESSION_ID> --start-ts 1000000,2000000 --end-ts 1500000,2500000
Note: A range holding fewer than 20 samples returns placeholder numbers, not real measurements. Widen the range.
To compare a run against a baseline:
metavr perf compare <BASELINE_ID> <COMPARISON_ID>
5. Open the trace in Perfetto
metavr perf open <SESSION_ID>
This serves the trace and opens your browser. It waits until the browser fetches the trace, and gives up after three minutes idle.
Profile the CPU with simpleperf
A Perfetto trace shows where time goes inside a frame. simpleperf answers a different question: why the CPU is slow. It needs the simpleperf binary on the device, and your app has to be running already.
metavr perf simpleperf classify --app com.example.myapp
This sorts the workload into CPU-bound, memory-bound, I/O-bound, or mixed, and explains the call. --duration <SECONDS> defaults to 10.
metavr perf simpleperf record --app com.example.myapp
This samples the app and lists the hottest functions. --frequency <HZ> defaults to 4000.
metavr perf simpleperf kernel-overhead --app com.example.myapp
This splits user and kernel cycles per thread.
Capture a memory snapshot
metavr perf memory-snapshot --app com.example.myapp
Snapshots land in a memory-snapshots folder. Change it with -o/--output <DIR>. Name a checkpoint with --label <LABEL>. Filenames carry a timestamp, so repeated snapshots never collide.
Ask your AI agent instead
With the Model Context Protocol (MCP) server connected, you can describe the goal in plain language. Ask your agent to capture a trace of your app and find the slowest frames, and it picks the steps and reports back.
Capture fails because Perfetto is missing on the device
Symptom:metavr perf capture reports that it cannot find the Perfetto binary on the headset.
Solution: The headset needs perfetto present. Confirm the device is in Developer Mode and shows up in metavr device list.
The first analysis command pauses
Symptom: Your first analyze-trace or query sits for a while before printing anything.
Solution: metavr is downloading Perfetto’s trace processor. It caches it, so later commands start right away. Run metavr tools install perfetto first to get it out of the way.
GPU counters return placeholder numbers
Symptom:metavr perf gpu-counters returns placeholder values in place of measurements.
Solution: The range held fewer than 20 samples. Widen the gap between --start-ts and --end-ts.
A trace you captured is gone
Symptom: A trace is missing under the name you expected.
Solution: Re-using an --output name overwrites the earlier trace. Run metavr perf traces to list what you still have.