In this guide, you'll learn how to:
The Perfetto SDK is a C++ library that allows you to instrument your application to record trace events. These events can then be visualized and analyzed with the Perfetto UI and Trace Processor.
Checkout the latest SDK release
git clone https://github.com/google/perfetto.git -b v50.1
The SDK consists of two files, sdk/perfetto.h
and sdk/perfetto.cc
. These are an amalgamation of the Client API designed to easy to integrate to existing build systems. The sources are self-contained and require only a C++17 compliant standard library.
Copy them in your project. The next steps assume they're in the perfetto/sdk
folder. Assuming your build looks like this:
You can add the perfetto static library like this:
Initialize perfetto in your program and define your tracing categories:
You can now add instrumentation points to your code. They will emit events when tracing is enabled.
The TRACE_EVENT
macro records a scoped event. The event starts when the macro is called and ends at the end of the current scope (e.g., when the function returns). This is the most common type of event and is useful for tracing the duration of a function.
The TRACE_EVENT_BEGIN
and TRACE_EVENT_END
macros can be used to record events that don't follow function scoping. TRACE_EVENT_BEGIN
starts an event, and TRACE_EVENT_END
ends the most recent event started on the same thread by default, but can be configured to work across threads and even across processes (see the Track Event documentation for more details). This is useful for tracing operations that span multiple functions.
The TRACE_COUNTER
macro records the value of a counter at a specific point in time. This is useful for tracking things like memory usage or the number of items in a queue.
You can start collecting events with:
And you can stop and save them into a file with:
You can now open the example.pftrace
file with https://ui.perfetto.dev/
It will show the events captured by the execution of your instrumentation points:
As well as visualizing traces on a timeline, Perfetto has support for querying traces using SQL. The easiest way to do this is using the query engine available directly in the UI.
In the Perfetto UI, click on the “Query (SQL)” tab in the left-hand menu.
This will open a two-part window. You can write your PerfettoSQL query in the top section and view the results in the bottom section.
You can then execute queries Ctrl/Cmd + Enter:
For example, by running:
SELECT dur AS duration_ns, EXTRACT_ARG(slice.arg_set_id, 'debug.player_number') AS player_number FROM slice WHERE slice.name = 'DrawPlayer';
you can see how many times the DrawPlayer
instrumentation point has been hit, how long each execution took and its player_number
annotation.
The framerate counter is available in the counter
table:
SELECT ts AS timestamp_ns, value AS frame_rate FROM counter JOIN track ON track.id = counter.track_id WHERE name = 'Framerate';
While in-app tracing is useful for understanding your application‘s behavior in isolation, its real power comes from combining it with a system-wide trace. This allows you to see how your app’s events correlate with system events like CPU scheduling, memory usage, and I/O, providing a complete picture of your app's performance in the context of the entire system.
To enable combined tracing, you need to change your application to connect to the system-wide tracing service and then use the standard system tracing tools to record a trace.
Modify your application code:
kSystemBackend
). This tells the Perfetto SDK to send trace events to the central system tracing service instead of collecting them within the app.perfetto::Tracing::NewTrace()
, tracing_session->Setup()
, tracing_session->StartBlocking()
, etc.). Your application now only acts as a producer of trace data, and the system tracing service will control when tracing starts and stops.Your main
function should now look like this:
#include <perfetto.h> // Define your categories as before. PERFETTO_DEFINE_CATEGORIES( perfetto::Category("rendering") .SetDescription("Events from the graphics subsystem"), perfetto::Category("network") .SetDescription("Network upload and download statistics")); PERFETTO_TRACK_EVENT_STATIC_STORAGE(); int main(int argc, char** argv) { // Connect to the system tracing service. perfetto::TracingInitArgs args; args.backends |= perfetto::kSystemBackend; perfetto::Tracing::Initialize(args); // Register your track event data source. perfetto::TrackEvent::Register(); // Your application logic goes here. // The TRACE_EVENT macros will now write to the system trace buffer // when tracing is enabled externally. // ... }
Record a system trace:
With your application running, you can now record a combined trace using the methods described in the Recording system traces guide.
When you configure your trace, you need to enable the track_event
data source in addition to any system data sources you want to collect (e.g., linux.ftrace
). This will ensure that your application's custom events are included in the trace.
When you open the resulting trace file in the Perfetto UI, you will see your application's custom tracks alongside the system-level tracks.
Now that you've recorded your first in-app trace, you can learn more about instrumenting your code: