blob: 783c989c7d4d4b0d62ef27b0161ecdac814fdaee [file] [log] [blame] [view]
Primiano Tuccia6624852020-05-21 19:12:50 +01001# Tracing SDK
2
Lalit Maganti03d178e2022-11-03 16:18:51 +00003The Perfetto Tracing SDK is a C++17 library that allows userspace applications
Primiano Tuccia6624852020-05-21 19:12:50 +01004to emit trace events and add more app-specific context to a Perfetto trace.
5
6When using the Tracing SDK there are two main aspects to consider:
7
81. Whether you are interested only in tracing events coming from your own app
9 or want to collect full-stack traces that overlay app trace events with
10 system trace events like scheduler traces, syscalls or any other Perfetto
11 data source.
12
132. For app-specific tracing, whether you need to trace simple types of timeline
14 events (e.g., slices, counters) or need to define complex data sources with a
15 custom strongly-typed schema (e.g., for dumping the state of a subsystem of
16 your app into the trace).
17
18For Android-only instrumentation, the advice is to keep using the existing
19[android.os.Trace (SDK)][atrace-sdk] / [ATrace_* (NDK)][atrace-ndk] if they
20are sufficient for your use cases. Atrace-based instrumentation is fully
21supported in Perfetto.
22See the [Data Sources -> Android System -> Atrace Instrumentation][atrace-ds]
23for details.
24
25## Getting started
26
Sami Kyostilafffa2ec2020-05-27 11:59:19 +010027TIP: The code from these examples is also available [in the
Primiano Tuccia3bddd62020-05-27 19:52:12 +010028repository](/examples/sdk/README.md).
Primiano Tuccia6624852020-05-21 19:12:50 +010029
30To start using the Client API, first check out the latest SDK release:
31
Sami Kyostilaeed625c2020-05-27 15:58:28 +010032```bash
Daniele Di Proietto52a99212023-11-15 18:34:36 +000033git clone https://android.googlesource.com/platform/external/perfetto -b v39.0
Primiano Tuccia6624852020-05-21 19:12:50 +010034```
35
36The SDK consists of two files, `sdk/perfetto.h` and `sdk/perfetto.cc`. These are
37an amalgamation of the Client API designed to easy to integrate to existing
Lalit Maganti03d178e2022-11-03 16:18:51 +000038build systems. The sources are self-contained and require only a C++17 compliant
Primiano Tuccia6624852020-05-21 19:12:50 +010039standard library.
40
41For example, to add the SDK to a CMake project, edit your CMakeLists.txt:
42
43```cmake
44cmake_minimum_required(VERSION 3.13)
45project(PerfettoExample)
46find_package(Threads)
47
48# Define a static library for Perfetto.
49include_directories(perfetto/sdk)
50add_library(perfetto STATIC perfetto/sdk/perfetto.cc)
51
52# Link the library to your main executable.
53add_executable(example example.cc)
54target_link_libraries(example perfetto ${CMAKE_THREAD_LIBS_INIT})
Daniele Di Proiettoe0c74302022-11-11 16:09:13 +000055
56if (WIN32)
57 # The perfetto library contains many symbols, so it needs the big object
58 # format.
59 target_compile_options(perfetto PRIVATE "/bigobj")
60 # Disable legacy features in windows.h.
61 add_definitions(-DWIN32_LEAN_AND_MEAN -DNOMINMAX)
62 # On Windows we should link to WinSock2.
63 target_link_libraries(example ws2_32)
64endif (WIN32)
65
66# Enable standards-compliant mode when using the Visual Studio compiler.
67if (MSVC)
68 target_compile_options(example PRIVATE "/permissive-")
69endif (MSVC)
Primiano Tuccia6624852020-05-21 19:12:50 +010070```
71
72Next, initialize Perfetto in your program:
73
74```C++
75#include <perfetto.h>
76
Huichun Feng89895d02022-05-21 16:03:55 +080077int main(int argc, char** argv) {
Primiano Tuccia6624852020-05-21 19:12:50 +010078 perfetto::TracingInitArgs args;
79
80 // The backends determine where trace events are recorded. You may select one
81 // or more of:
82
83 // 1) The in-process backend only records within the app itself.
84 args.backends |= perfetto::kInProcessBackend;
85
86 // 2) The system backend writes events into a system Perfetto daemon,
87 // allowing merging app and system events (e.g., ftrace) on the same
88 // timeline. Requires the Perfetto `traced` daemon to be running (e.g.,
89 // on Android Pie and newer).
90 args.backends |= perfetto::kSystemBackend;
91
92 perfetto::Tracing::Initialize(args);
93}
94```
95
96You are now ready to instrument your app with trace events.
97
98## Custom data sources vs Track events
99
100The SDK offers two abstraction layers to inject tracing data, built on top of
101each other, which trade off code complexity vs expressive power:
102[track events](#track-events) and [custom data sources](#custom-data-sources).
103
104### Track events
105
106Track events are the suggested option when dealing with app-specific tracing as
107they take care of a number of subtleties (e.g., thread safety, flushing, string
108interning).
109Track events are time bounded events (e.g., slices, counter) based on simple
Sami Kyostila3d609432020-06-25 15:59:29 +0100110`TRACE_EVENT` annotation tags in the codebase, like this:
Primiano Tuccia6624852020-05-21 19:12:50 +0100111
112```c++
113#include <perfetto.h>
114
115PERFETTO_DEFINE_CATEGORIES(
116 perfetto::Category("rendering")
117 .SetDescription("Events from the graphics subsystem"),
118 perfetto::Category("network")
119 .SetDescription("Network upload and download statistics"));
120
Daniele Di Proietto15c1f622022-10-19 11:26:22 +0100121PERFETTO_TRACK_EVENT_STATIC_STORAGE();
Primiano Tuccia6624852020-05-21 19:12:50 +0100122...
123
Huichun Feng89895d02022-05-21 16:03:55 +0800124int main(int argc, char** argv) {
Primiano Tuccia6624852020-05-21 19:12:50 +0100125 ...
126 perfetto::Tracing::Initialize(args);
127 perfetto::TrackEvent::Register();
128}
129
130...
131
132void LayerTreeHost::DoUpdateLayers() {
133 TRACE_EVENT("rendering", "LayerTreeHost::DoUpdateLayers");
134 ...
135 for (PictureLayer& pl : layers) {
136 TRACE_EVENT("rendering", "PictureLayer::Update");
137 pl.Update();
138 }
139}
140```
141
142Which are rendered in the UI as follows:
143
144![Track event example](/docs/images/track-events.png)
145
146Track events are the best default option and serve most tracing use cases with
147very little complexity.
148
149To include your new track events in the trace, ensure that the `track_event`
150data source is included in the trace config. If you do not specify any
151categories then all non-debug categories will be included by default. However,
152you can also add just the categories you are interested in like so:
153
154```protobuf
155data_sources {
156 config {
157 name: "track_event"
158 track_event_config {
159 enabled_categories: "rendering"
160 }
161 }
162}
163```
164
165See the [Track events page](track-events.md) for full instructions.
166
167### Custom data sources
168
169For most uses, track events are the most straightforward way of instrumenting
170apps for tracing. However, in some rare circumstances they are not
171flexible enough, e.g., when the data doesn't fit the notion of a track or is
172high volume enough that it needs a strongly typed schema to minimize the size of
173each event. In this case, you can implement a *custom data source* for
174Perfetto.
175
176Unlike track events, when working with custom data sources, you will also need
177corresponding changes in [trace processor](/docs/analysis/trace-processor.md)
178to enable importing your data format.
179
Primiano Tucci62f76f02020-06-23 09:01:46 +0100180A custom data source is a subclass of `perfetto::DataSource`. Perfetto will
Primiano Tuccia6624852020-05-21 19:12:50 +0100181automatically create one instance of the class for each tracing session it is
182active in (usually just one).
183
184```C++
185class CustomDataSource : public perfetto::DataSource<CustomDataSource> {
186 public:
187 void OnSetup(const SetupArgs&) override {
188 // Use this callback to apply any custom configuration to your data source
189 // based on the TraceConfig in SetupArgs.
190 }
191
192 void OnStart(const StartArgs&) override {
193 // This notification can be used to initialize the GPU driver, enable
194 // counters, etc. StartArgs will contains the DataSourceDescriptor,
195 // which can be extended.
196 }
197
198 void OnStop(const StopArgs&) override {
199 // Undo any initialization done in OnStart.
200 }
201
202 // Data sources can also have per-instance state.
203 int my_custom_state = 0;
204};
205
206PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
207```
208
209The data source's static data should be defined in one source file like this:
210
211```C++
212PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
213```
214
215Custom data sources need to be registered with Perfetto:
216
217```C++
Huichun Feng89895d02022-05-21 16:03:55 +0800218int main(int argc, char** argv) {
Primiano Tuccia6624852020-05-21 19:12:50 +0100219 ...
220 perfetto::Tracing::Initialize(args);
221 // Add the following:
222 perfetto::DataSourceDescriptor dsd;
223 dsd.set_name("com.example.custom_data_source");
224 CustomDataSource::Register(dsd);
225}
226```
227
228As with all data sources, the custom data source needs to be specified in the
229trace config to enable tracing:
230
231```C++
232perfetto::TraceConfig cfg;
233auto* ds_cfg = cfg.add_data_sources()->mutable_config();
234ds_cfg->set_name("com.example.custom_data_source");
235```
236
237Finally, call the `Trace()` method to record an event with your custom data
238source. The lambda function passed to that method will only be called if tracing
239is enabled. It is always called synchronously and possibly multiple times if
240multiple concurrent tracing sessions are active.
241
242```C++
243CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
244 auto packet = ctx.NewTracePacket();
245 packet->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs());
246 packet->set_for_testing()->set_str("Hello world!");
247});
248```
249
250If necessary the `Trace()` method can access the custom data source state
251(`my_custom_state` in the example above). Doing so, will take a mutex to
252ensure data source isn't destroyed (e.g., because of stopping tracing) while
253the `Trace()` method is called on another thread. For example:
254
255```C++
256CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
257 auto safe_handle = trace_args.GetDataSourceLocked(); // Holds a RAII lock.
258 DoSomethingWith(safe_handle->my_custom_state);
259});
260```
261
262## In-process vs System mode
263
264The two modes are not mutually exclusive. An app can be configured to work
265in both modes and respond both to in-process tracing requests and system
266tracing requests. Both modes generate the same trace file format.
267
268### In-process mode
269
270In this mode both the perfetto service and the app-defined data sources are
271hosted fully in-process, in the same process of the profiled app. No connection
272to the system `traced` daemon will be attempted.
273
274In-process mode can be enabled by setting
275`TracingInitArgs.backends = perfetto::kInProcessBackend` when initializing the
276SDK, see examples below.
277
278This mode is used to generate traces that contain only events emitted by
279the app, but not other types of events (e.g. scheduler traces).
280
281The main advantage is that by running fully in-process, it doesn't require any
282special OS privileges and the profiled process can control the lifecycle of
283tracing sessions.
284
285This mode is supported on Android, Linux, MacOS and Windows.
286
287### System mode
288
289In this mode the app-defined data sources will connect to the external `traced`
290service using the [IPC over UNIX socket][ipc].
291
292System mode can be enabled by setting
293`TracingInitArgs.backends = perfetto::kSystemBackend` when initializing the SDK,
294see examples below.
295
296The main advantage of this mode is that it is possible to create fused traces where
297app events are overlaid on the same timeline of OS events. This enables
298full-stack performance investigations, looking all the way through syscalls and
299kernel scheduling events.
300
301The main limitation of this mode is that it requires the external `traced` daemon
302to be up and running and reachable through the UNIX socket connection.
303
304This is suggested for local debugging or lab testing scenarios where the user
305(or the test harness) can control the OS deployment (e.g., sideload binaries on
306Android).
307
308When using system mode, the tracing session must be controlled from the outside,
309using the `perfetto` command-line client
310(See [reference](/docs/reference/perfetto-cli)). This is because when collecting
311system traces, tracing data producers are not allowed to read back the trace
312data as it might disclose information about other processes and allow
313side-channel attacks.
314
315* On Android 9 (Pie) and beyond, traced is shipped as part of the platform.
316* On older versions of Android, traced can be built from sources using the
317 the [standalone NDK-based workflow](/docs/contributing/build-instructions.md)
318 and sideloaded via adb shell.
Primiano Tucci77b30ec2023-03-15 17:04:52 +0000319* On Linux and MacOS and Windows `traced` must be built and run separately. See
320 the [Linux quickstart](/docs/quickstart/linux-tracing.md) for instructions.
321* On Windows the tracing protocol works over TCP/IP (
Lalit Maganti9e0146e2023-07-06 23:15:24 +0100322 [127.0.0.1:32278](https://cs.android.com/android/platform/superproject/+/main:external/perfetto/src/tracing/ipc/default_socket.cc;l=75;drc=4f88a2fdfd3801c109d5e927b8206f9756288b12)
Primiano Tucci77b30ec2023-03-15 17:04:52 +0000323 ) + named shmem.
Primiano Tuccia6624852020-05-21 19:12:50 +0100324
325## {#recording} Recording traces through the API
326
327_Tracing through the API is currently only supported with the in-process mode.
328When using system mode, use the `perfetto` cmdline client (see quickstart
329guides)._
330
331First initialize a [TraceConfig](/docs/reference/trace-config-proto.autogen)
332message which specifies what type of data to record.
333
334If your app includes [track events](track-events.md) (i.e, `TRACE_EVENT`), you
335typically want to choose the categories which are enabled for tracing.
336
337By default, all non-debug categories are enabled, but you can enable a specific
338one like this:
339
340```C++
341perfetto::protos::gen::TrackEventConfig track_event_cfg;
342track_event_cfg.add_disabled_categories("*");
343track_event_cfg.add_enabled_categories("rendering");
344```
345
346Next, build the main trace config together with the track event part:
347
348```C++
349perfetto::TraceConfig cfg;
350cfg.add_buffers()->set_size_kb(1024); // Record up to 1 MiB.
351auto* ds_cfg = cfg.add_data_sources()->mutable_config();
352ds_cfg->set_name("track_event");
353ds_cfg->set_track_event_config_raw(track_event_cfg.SerializeAsString());
354```
355
356If your app includes a custom data source, you can also enable it here:
357
358```C++
359ds_cfg = cfg.add_data_sources()->mutable_config();
360ds_cfg->set_name("my_data_source");
361```
362
363After building the trace config, you can begin tracing:
364
365```C++
366std::unique_ptr<perfetto::TracingSession> tracing_session(
367 perfetto::Tracing::NewTrace());
368tracing_session->Setup(cfg);
369tracing_session->StartBlocking();
370```
371
372TIP: API methods with `Blocking` in their name will suspend the calling thread
373 until the respective operation is complete. There are also asynchronous
374 variants that don't have this limitation.
375
376Now that tracing is active, instruct your app to perform the operation you
377want to record. After that, stop tracing and collect the
378protobuf-formatted trace data:
379
380```C++
381tracing_session->StopBlocking();
382std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
383
384// Write the trace into a file.
385std::ofstream output;
Carmen Jacksonaad2d912021-03-15 10:22:29 -0700386output.open("example.perfetto-trace", std::ios::out | std::ios::binary);
Primiano Tuccia6624852020-05-21 19:12:50 +0100387output.write(&trace_data[0], trace_data.size());
388output.close();
389```
390
391To save memory with longer traces, you can also tell Perfetto to write
392directly into a file by passing a file descriptor into Setup(), remembering
393to close the file after tracing is done:
394
395```C++
Carmen Jacksonaad2d912021-03-15 10:22:29 -0700396int fd = open("example.perfetto-trace", O_RDWR | O_CREAT | O_TRUNC, 0600);
Primiano Tuccia6624852020-05-21 19:12:50 +0100397tracing_session->Setup(cfg, fd);
398tracing_session->StartBlocking();
399// ...
400tracing_session->StopBlocking();
401close(fd);
402```
403
404The resulting trace file can be directly opened in the [Perfetto
405UI](https://ui.perfetto.dev) or the [Trace Processor](/docs/analysis/trace-processor.md).
406
407[ipc]: /docs/design-docs/api-and-abi.md#socket-protocol
408[atrace-ds]: /docs/data-sources/atrace.md
409[atrace-ndk]: https://developer.android.com/ndk/reference/group/tracing
Sami Kyostila0a597c22020-05-27 10:31:19 +0100410[atrace-sdk]: https://developer.android.com/reference/android/os/Trace