• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Trace configuration
2
3Unlike many always-on logging systems (e.g. Linux's rsyslog, Android's logcat),
4in Perfetto all tracing data sources are idle by default and record data only
5when instructed to do so.
6
7Data sources record data only when one (or more) tracing sessions are active.
8A tracing session is started by invoking the `perfetto` cmdline client and
9passing a config (see QuickStart guide for
10[Android](/docs/quickstart/android-tracing.md),
11[Linux](/docs/quickstart/linux-tracing.md), or [Chrome on desktop](/docs/quickstart/chrome-tracing.md)).
12
13A simple trace config looks like this:
14
15```protobuf
16duration_ms: 10000
17
18buffers {
19  size_kb: 65536
20  fill_policy: RING_BUFFER
21}
22
23data_sources {
24  config {
25    name: "linux.ftrace"
26    target_buffer: 0
27    ftrace_config {
28      ftrace_events: "sched_switch"
29      ftrace_events: "sched_wakeup"
30    }
31  }
32}
33
34````
35
36And is used as follows:
37
38```bash
39perfetto --txt -c config.pbtx -o trace_file.perfetto-trace
40```
41
42TIP: Some more complete examples of trace configs can be found in the repo in
43[`/test/configs/`](/test/configs/).
44
45NOTE: If you are tracing on Android using adb and experiencing problems, see
46      [the Android section](#android) below.
47
48## TraceConfig
49
50The TraceConfig is a protobuf message
51([reference docs](/docs/reference/trace-config-proto.autogen)) that defines:
52
531. The general behavior of the whole tracing system, e.g.:
54    * The max duration of the trace.
55    * The number of in-memory buffers and their size.
56    * The max size of the output trace file.
57
582. Which data sources to enable and their configuration, e.g.:
59    * For the [kernel tracing data source](/docs/data-sources/cpu-scheduling.md)
60    , which ftrace events to enable.
61    * For the [heap profiler](/docs/data-sources/native-heap-profiler.md), the
62    target process name and sampling rate.
63
64    See the _data sources_ section of the docs for details on how to
65    configure the data sources bundled with Perfetto.
66
673. The `{data source} x {buffer}` mappings: which buffer each data
68    source should write into (see [buffers section](#buffers) below).
69
70The tracing service (`traced`) acts as a configuration dispatcher: it receives
71a config from the `perfetto` cmdline client (or any other
72[Consumer](/docs/concepts/service-model.md#consumer)) and forwards parts of the
73config to the various [Producers](/docs/concepts/service-model.md#producer)
74connected.
75
76When a tracing session is started by a consumer, the tracing service will:
77
78* Read the outer section of the TraceConfig (e.g. `duration_ms`, `buffers`) and
79  use that to determine its own behavior.
80* Read the list of data sources in the `data_sources` section. For each data
81  source listed in the config, if a corresponding name (`"linux.ftrace"` in the
82  example below) was registered, the service will ask the producer process to
83  start that data source, passing it the raw bytes of the
84  [`DataSourceConfig` subsection][dss] verbatim to the data source (See
85  backward/forward compat section below).
86
87![TraceConfig diagram](/docs/images/trace_config.png)
88
89[dss]: /docs/reference/trace-config-proto.autogen#DataSourceConfig
90
91## Buffers
92
93The buffer sections define the number, size and policy of the in-memory buffers
94owned by the tracing service. It looks as follows:
95
96```protobuf
97# Buffer #0
98buffers {
99  size_kb: 4096
100  fill_policy: RING_BUFFER
101}
102
103# Buffer #1
104buffers {
105  size_kb: 8192
106  fill_policy: DISCARD
107}
108```
109
110Each buffer has a fill policy which is either:
111
112* RING_BUFFER (default): the buffer behaves like a ring buffer and writes when
113  full will wrap over and replace the oldest trace data in the buffer.
114
115* DISCARD: the buffer stops accepting data once full. Further write attempts are
116  dropped.
117
118WARNING: DISCARD can have unexpected side-effect with data sources that commit
119data at the end of the trace.
120
121A trace config must define at least one buffer to be valid. In the simplest case
122all data sources will write their trace data into the same buffer.
123
124 While this is
125fine for most basic cases, it can be problematic in cases where different data
126sources write at significantly different rates.
127
128For instance, imagine a trace config that enables both:
129
1301. The kernel scheduler tracer. On a typical Android phone this records
131   ~10000 events/second, writing ~1 MB/s of trace data into the buffer.
132
1332. Memory stat polling. This data source writes the contents of /proc/meminfo
134   into the trace buffer and is configured to poll every 5 seconds, writing
135   ~100 KB per poll interval.
136
137If both data sources are configured to write into the same buffer and such
138buffer is set to 4MB, most traces will contain only one memory snapshot. There
139are very good chances that most traces won't contain any memory snapshot at all,
140even if the 2nd data sources was working perfectly.
141This is because during the 5 s. polling interval, the scheduler data source can
142end up filling the whole buffer, pushing the memory snapshot data out of the
143buffer.
144
145## Dynamic buffer mapping
146
147Data-source <> buffer mappings are dynamic in Perfetto.
148In the simplest case a tracing session can define only one buffer. By default,
149all data sources will record data into that one buffer.
150
151In cases like the example above, it might be preferable separating these data
152sources into different buffers.
153This can be achieved with the `target_buffer` field of the TraceConfig.
154
155![Buffer mapping](/docs/images/trace_config_buffer_mapping.png)
156
157Can be achieved with:
158
159```protobuf
160data_sources {
161  config {
162    name: "linux.ftrace"
163    target_buffer: 0       # <-- This goes into buffer 0.
164    ftrace_config { ... }
165  }
166}
167
168data_sources: {
169  config {
170      name: "linux.sys_stats"
171      target_buffer: 1     # <-- This goes into buffer 1.
172      sys_stats_config { ... }
173  }
174}
175
176data_sources: {
177  config {
178    name: "android.heapprofd"
179    target_buffer: 1       # <-- This goes into buffer 1 as well.
180    heapprofd_config { ... }
181  }
182}
183```
184
185## PBTX vs binary format
186
187There are two ways to pass the trace config when using the `perfetto` cmdline
188client format:
189
190#### Text format
191
192It is the preferred format for human-driven workflows and exploration. It
193allows to pass directly the text file in the PBTX (ProtoBuf TeXtual
194representation) syntax, for the schema defined in the
195[trace_config.proto](/protos/perfetto/config/trace_config.proto)
196(see [reference docs](/docs/reference/trace-config-proto.autogen))
197
198When using this mode pass the `--txt` flag to `perfetto` to indicate the config
199should be interpreted as a PBTX file:
200
201```bash
202perfetto -c /path/to/config.pbtx --txt -o trace_file.perfetto-trace
203```
204
205NOTE: The `--txt` option has been introduced only in Android 10 (Q). Older
206versions support only the binary format.
207
208WARNING: Do not use the text format for machine-to-machine interaction
209benchmark, scripts and tools) as it's more prone to breakages (e.g. if a field
210is renamed or an enum is turned into an integer)
211
212#### Binary format
213
214It is the preferred format for machine-to-machine (M2M) interaction. It involves
215passing the protobuf-encoded binary of the TraceConfig message.
216This can be obtained passing the PBTX in input to the protobuf's `protoc`
217compiler (which can be downloaded
218[here](https://github.com/protocolbuffers/protobuf/releases)).
219
220```bash
221cd ~/code/perfetto  # external/perfetto in the Android tree.
222
223protoc --encode=perfetto.protos.TraceConfig \
224        -I. protos/perfetto/config/perfetto_config.proto \
225        < config.txpb \
226        > config.bin
227```
228
229and then passing it to perfetto as follows, without the `--txt` argument:
230
231```bash
232perfetto -c config.bin -o trace_file.perfetto-trace
233```
234
235## {#long-traces} Streaming long traces
236
237By default Perfetto keeps the full trace buffer(s) in memory and writes it into
238the destination file (the `-o` cmdline argument) only at the end of the tracing
239session. This is to reduce the perf-intrusiveness of the tracing system.
240This, however, limits the max size of the trace to the physical memory size of
241the device, which is often too limiting.
242
243In some cases (e.g., benchmarks, hard to repro cases) it is desirable to capture
244traces that are way larger than that, at the cost of extra I/O overhead.
245
246To achieve that, Perfetto allows to periodically write the trace buffers into
247the target file (or stdout) using the following TraceConfig fields:
248
249* `write_into_file (bool)`:
250When true periodically drains the trace buffers into the output
251file. When this option is enabled, the userspace buffers need to be just
252big enough to hold tracing data between two write periods.
253The buffer sizing depends on the activity of the device.
254The data rate of a typical trace is ~1-4 MB/s. So a 16MB in-memory buffer can
255hold for up write periods of ~4 seconds before starting to lose data.
256
257* `file_write_period_ms (uint32)`:
258Overrides the default drain period (5s). Shorter periods require a smaller
259userspace buffer but increase the performance intrusiveness of tracing. If
260the period given is less than 100ms, the tracing service will use a period
261of 100ms.
262
263* `max_file_size_bytes (uint64)`:
264If set, stops the tracing session after N bytes have been written. Used to
265cap the size of the trace.
266
267For a complete example of a working trace config in long-tracing mode see
268[`/test/configs/long_trace.cfg`](/test/configs/long_trace.cfg).
269
270Summary: to capture a long trace just set `write_into_file:true`, set a long
271         `duration_ms` and use an in-memory buffer size of 32MB or more.
272
273## Data-source specific config
274
275Alongside the trace-wide configuration parameters, the trace config also defines
276data-source-specific behaviors. At the proto schema level, this is defined in
277the `DataSourceConfig` section of `TraceConfig`:
278
279From [data_source_config.proto](/protos/perfetto/config/data_source_config.proto):
280
281```protobuf
282message TraceConfig {
283  ...
284  repeated DataSource data_sources = 2;  // See below.
285}
286
287message DataSource {
288  optional protos.DataSourceConfig config = 1;  // See below.
289  ...
290}
291
292message DataSourceConfig {
293  optional string name = 1;
294  ...
295  optional FtraceConfig ftrace_config = 100 [lazy = true];
296  ...
297  optional AndroidPowerConfig android_power_config = 106 [lazy = true];
298}
299```
300
301Fields like `ftrace_config`, `android_power_config` are examples of data-source
302specific configs. The tracing service will completely ignore the contents of
303those fields and route the whole DataSourceConfig object to any data source
304registered with the same name.
305
306The `[lazy=true]` marker has a special implication in the
307[protozero](/docs/design-docs/protozero.md) code generator. Unlike standard
308nested messages, it generates raw accessors (e.g.,
309`const std::string& ftrace_config_raw()` instead of
310`const protos::FtraceConfig& ftrace_config()`). This is to avoid injecting too
311many `#include` dependencies and avoiding binary size bloat in the code that
312implements data sources.
313
314#### A note on backwards/forward compatibility
315The tracing service will route the raw binary blob of the `DataSourceConfig`
316message to the data sources with a matching name, without attempting to decode
317and re-encode it. If the `DataSourceConfig` section of the trace config contains
318a new field that didn't exist at the time when the service was built, the
319service will still pass the `DataSourceConfig` through to the data source.
320This allows to introduced new data sources without needing the service to
321know anything about them upfront.
322
323TODO: we are aware of the fact that today extending the `DataSourceConfig` with
324a custom proto requires changing the `data_source_config.proto` in the Perfetto
325repo, which is unideal for external projects. The long-term plan is to reserve
326a range of fields for non-upstream extensions and provide generic templated
327accessors for client code. Until then, we accept patches upstream to introduce
328ad-hoc configurations for your own data sources.
329
330## Multi-process data sources
331
332Some data sources are singletons. E.g., in the case of scheduler tracing that
333Perfetto ships on Android, there is only data source for the whole system,
334owned by the `traced_probes` service.
335
336However, in the general case multiple processes can advertise the same data
337source. This is the case, for instance, when using the
338[Perfetto SDK](/docs/instrumentation/tracing-sdk.md) for userspace
339instrumentation.
340
341If this happens, when starting a tracing session that specifies that data
342source in the trace config, Perfetto by default will ask all processes that
343advertise that data source to start it.
344
345In some cases it might be desirable to further limit the enabling of the data
346source to a specific process (or set of processes). That is possible through the
347`producer_name_filter` and `producer_name_regex_filter`.
348
349NOTE: the typical Perfetto run-time model is: one process == one Perfetto
350      Producer; one Producer typically hosts multiple data sources.
351
352When those filters are set, the Perfetto tracing service will activate the data
353source only in the subset of producers matching the filter.
354
355Example:
356
357```protobuf
358buffers {
359  size_kb: 4096
360}
361
362data_sources {
363  config {
364    name: "track_event"
365  }
366  # Enable the data source only on Chrome and Chrome canary.
367  producer_name_filter: "com.android.chrome"
368  producer_name_filter: "com.google.chrome.canary"
369}
370```
371
372## Triggers
373
374In nominal conditions, a tracing session has a lifecycle that simply matches the
375invocation of the `perfetto` cmdline client: trace data recording starts when
376the TraceConfig is passed to `perfetto` and ends when either the
377`TraceConfig.duration_ms` has elapsed, or when the cmdline client terminates.
378
379Perfetto supports an alternative mode of either starting or stopping the trace
380which is based on triggers. The overall idea is to declare in the trace config
381itself:
382
383* A set of triggers, which are just free-form strings.
384* Whether a given trigger should cause the trace to be started or stopped, and
385  the start/stop delay.
386
387Why using triggers? Why can't one just start perfetto or kill(SIGTERM) it when
388needed? The rationale of all this is the security model: in most Perfetto
389deployments (e.g., on Android) only privileged entities (e.g., adb shell) can
390configure/start/stop tracing. Apps are unprivileged in this sense and they
391cannot control tracing.
392
393Triggers offer a way to unprivileged apps to control, in a limited fashion, the
394lifecycle of a tracing session. The conceptual model is:
395
396* The privileged Consumer (see
397  [_Service model_](/docs/concepts/service-model.md)), i.e. the entity
398  that is normally authorized to start tracing (e.g., adb shell in Android),
399  declares upfront what are the possible trigger names for the trace and what
400  they will do.
401* Unprivileged entities (any random app process) can activate those triggers.
402  Unprivileged entities don't get a say on what the triggers will do, they only
403  communicate that an event happened.
404
405Triggers can be signaled via the cmdline util
406
407```bash
408/system/bin/trigger_perfetto "trigger_name"
409```
410
411(or also by starting an independent trace session which uses only the
412`activate_triggers: "trigger_name"` field in the config)
413
414There are two types of triggers:
415
416#### Start triggers
417
418Start triggers allow activating a tracing session only after some significant
419event has happened. Passing a trace config that has `START_TRACING` trigger
420causes the tracing session to stay idle (i.e. not recording any data) until either
421the trigger is hit or the `trigger_timeout_ms` timeout is hit.
422
423`trace_duration_ms` and triggered traces can not be used at the same time.
424
425Example config:
426```protobuf
427# If the "myapp_is_slow" is hit, the trace starts recording data and will be
428# stopped after 5s.
429trigger_config {
430  trigger_mode: START_TRACING
431  triggers {
432    name: "myapp_is_slow"
433    stop_delay_ms: 5000
434  }
435  # If no trigger is hit, the trace will end without having recorded any data
436  # after 30s.
437  trigger_timeout_ms: 30000
438}
439
440# The rest of the config is as usual.
441buffers { ... }
442data_sources { ... }
443```
444
445#### Stop triggers
446
447STOP_TRACING triggers allow to prematurely finalize a trace when the trigger is
448hit. In this mode the trace starts immediately when the `perfetto` client is
449invoked (like in nominal cases). The trigger acts as a premature finalization
450signal.
451
452This can be used to use perfetto in flight-recorder mode. By starting a trace
453with buffers configured in `RING_BUFFER` mode and `STOP_TRACING` triggers,
454the trace will be recorded in a loop and finalized when the culprit event is
455detected. This is key for events where the root cause is in the recent past
456(e.g., the app detects a slow scroll or a missing frame).
457
458Example config:
459```protobuf
460# If no trigger is hit, the trace will end after 30s.
461trigger_timeout_ms: 30000
462
463# If the "missed_frame" is hit, the trace is stopped after 1s.
464trigger_config {
465  trigger_mode: STOP_TRACING
466  triggers {
467    name: "missed_frame"
468    stop_delay_ms: 1000
469  }
470}
471
472# The rest of the config is as usual.
473buffers { ... }
474data_sources { ... }
475```
476
477## Android
478
479On Android, there are some caveats around using `adb shell`
480
481* Ctrl+C, which normally causes a graceful termination of the trace, is not
482  propagated by ADB when using `adb shell perfetto` but only when using an
483  interactive PTY-based session via `adb shell`.
484* On non-rooted devices before Android 12, the config can only be passed as
485  `cat config | adb shell perfetto -c -` (-: stdin) because of over-restrictive
486  SELinux rules. Since Android 12 `/data/misc/perfetto-configs` can be used for
487  storing configs.
488* On devices before Android 10, adb cannot directly pull
489  `/data/misc/perfetto-traces`. Use
490  `adb shell cat /data/misc/perfetto-traces/trace > trace` to work around.
491* When capturing longer traces, e.g. in the context of benchmarks or CI, use
492  `PID=$(perfetto --background)` and then `kill $PID` to stop.
493
494
495## Other resources
496
497* [TraceConfig Reference](/docs/reference/trace-config-proto.autogen)
498* [Buffers and dataflow](/docs/concepts/buffers.md)
499