docs/getting-started/periodic-trace-snapshots.md
In this guide, you'll learn how to:
--clone-by-name.This workflow is useful when you need to repeatedly observe system metrics (CPU frequency, power rails, temperatures, etc.) while iterating on device or system configuration, without restarting tracing each time.
Imagine you are tuning device or system parameters (e.g. writing to /proc or
/sys nodes) and want to see the effect on power, thermals and CPU behavior
within seconds. The traditional workflow of "start trace, stop trace, pull,
analyze" adds unnecessary friction.
With periodic trace snapshots you start a single ring-buffer trace once, then clone it as many times as you like. Each clone is an independent snapshot of the ring buffer at that point in time; the original trace keeps running undisturbed.
Whenever you want to capture the current state of the ring buffer, clone the session by name:
<?tabs> TAB: Android ```bash adb shell perfetto --clone-by-name my_snapshot \ -o /data/misc/perfetto-traces/snapshot_1.pftrace ``` This creates a read-only copy of the ring buffer contents at that instant. The original tracing session continues to run. You can repeat this as many times as you like, giving each snapshot a different output file name: ```bash # After making a system/device parameter change... adb shell perfetto --clone-by-name my_snapshot \ -o /data/misc/perfetto-traces/snapshot_2.pftrace ``` TAB: Linux ```bash perfetto --clone-by-name my_snapshot \ -o /tmp/snapshot_1.pftrace # Or with tracebox: ./tracebox --clone-by-name my_snapshot \ -o /tmp/snapshot_1.pftrace ``` This creates a read-only copy of the ring buffer contents at that instant. The original tracing session continues to run. You can repeat this as many times as you like, giving each snapshot a different output file name: ```bash # After making a system parameter change... perfetto --clone-by-name my_snapshot \ -o /tmp/snapshot_2.pftrace ``` </tabs?>You can analyze the snapshot using the trace_processor_shell command line,
the Python API, or by opening it in the
Perfetto UI.
Run a one-off query directly from the command line using the query subcommand:
trace_processor_shell query /tmp/snapshot_1.pftrace "
INCLUDE PERFETTO MODULE linux.cpu.frequency;
SELECT * FROM cpu_frequency_counters LIMIT 100;
"
Or open an interactive SQL shell to explore the data:
trace_processor_shell /tmp/snapshot_1.pftrace
Here are some useful queries:
INCLUDE PERFETTO MODULE linux.cpu.frequency;
SELECT *
FROM cpu_frequency_counters
LIMIT 100;
INCLUDE PERFETTO MODULE android.power_rails;
SELECT *
FROM android_power_rails_counters
LIMIT 100;
SELECT ts, t.name, value
FROM counter AS c
LEFT JOIN counter_track AS t ON c.track_id = t.id
WHERE t.name GLOB 'batt.*';
SELECT ts, t.name, value
FROM counter AS c
LEFT JOIN counter_track AS t ON c.track_id = t.id
WHERE t.name GLOB '*thermal*';
The perfetto Python package lets you load traces and query them
programmatically, which is convenient for building custom dashboards or
post-processing data with Pandas / Polars. Install it with:
pip install perfetto
Example:
from perfetto.trace_processor import TraceProcessor
tp = TraceProcessor(trace='/tmp/snapshot_1.pftrace')
# Query CPU frequency as a Pandas DataFrame.
qr = tp.query("""
INCLUDE PERFETTO MODULE linux.cpu.frequency;
SELECT cpu, ts, freq
FROM cpu_frequency_counters
""")
df = qr.as_pandas_dataframe()
print(df.to_string())
# Plot frequency over time for each CPU.
import matplotlib.pyplot as plt
for cpu, group in df.groupby('cpu'):
plt.plot(group['ts'], group['freq'], label=f'cpu {cpu}')
plt.legend()
plt.xlabel('Timestamp (ns)')
plt.ylabel('Frequency (kHz)')
plt.show()
See the Trace Processor Python docs for more details.
If you want to analyze multiple snapshots together, Batch Trace Processor lets you run a single query across a set of traces in one go.
A simple shell loop can take a snapshot every N seconds and run a query against it:
<?tabs> TAB: Android ```bash for i in $(seq 1 10); do SNAP="/data/misc/perfetto-traces/snap_${i}.pftrace" adb shell perfetto --clone-by-name my_snapshot -o "$SNAP" adb pull "$SNAP" /tmp/ echo "=== Snapshot $i ===" trace_processor_shell query /tmp/"snap_${i}.pftrace" " INCLUDE PERFETTO MODULE linux.cpu.frequency; SELECT cpu, avg(freq) AS avg_freq_khz FROM cpu_frequency_counters GROUP BY cpu; " sleep 5 done ``` TAB: Linux ```bash for i in $(seq 1 10); do SNAP="/tmp/snap_${i}.pftrace" perfetto --clone-by-name my_snapshot -o "$SNAP" echo "=== Snapshot $i ===" trace_processor_shell query "$SNAP" " INCLUDE PERFETTO MODULE linux.cpu.frequency; SELECT cpu, avg(freq) AS avg_freq_khz FROM cpu_frequency_counters GROUP BY cpu; " sleep 5 done ``` </tabs?>android.power polls at the configured battery_poll_ms
interval, and some data sources only write data on trace start or stop. The
snapshot will contain whatever has been written to the ring buffer up to that
point.size_kb if you find gaps.--clone-by-name flag requires Perfetto v49+.
On Android this means Android 14 (U) or later. On Linux, ensure you are
using a recent tracebox or Perfetto build.tracefs. Rather than running as root, chown the directory to
your user: sudo chown -R $USER /sys/kernel/tracing.power/cpu_frequency
ftrace event is not emitted because frequency scaling is managed internally
by the CPU. Use the linux.sys_stats polling data source with
cpufreq_period_ms as a fallback.