<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet href="/feed.css?v=208f42b55cff" type="text/css"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:site="https://lalitm.com/feed/ns#"><channel><title>Lalit Maganti (Tag: Tracing)</title><link>https://lalitm.com/tags/tracing/</link><description>Recent content tagged Tracing on Lalit Maganti</description><site:notice>This is a feed.
Feeds let you subscribe to updates from this site using a feed reader. Copy this page's URL from your address bar and paste it into your reader.
New to feeds? Read: https://aboutfeeds.com</site:notice><docs>https://aboutfeeds.com</docs><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 03 Jul 2026 00:23:00 +0100</lastBuildDate><atom:link href="https://lalitm.com/tags/tracing/index.xml" rel="self" type="application/rss+xml"/><item><title>Perfetto v57: fixing PyTorch traces, plus journald logs and an AI skill</title><link>https://lalitm.com/post/perfetto-v57/</link><pubDate>Fri, 03 Jul 2026 00:23:00 +0100</pubDate><guid>https://lalitm.com/post/perfetto-v57/</guid><description>We just released Perfetto v57 and I wanted to share the new things I’m most excited about. This is something I wanted to do for past releases but I just never quite got round to it. It’s also something I plan on doing more of going forward: there might even be dedicated pieces if I think the feature deserves it!
PyTorch traces reliably work!# What I’m most excited about in this release isn’t a feature but a bugfix. If you used the PyTorch profiler and opened the resulting trace in Perfetto, there was a decent chance some of your events would just not show up; specifically this would happen when these events overlapped each other on a single track.
Technically, PyTorch is in the wrong here. The Chrome Trace Event (JSON) format says duration events on a track have to nest and can’t overlap; if you need overlap, you’re supposed to use async events. chrome://tracing appears to handle them, but its rendering is actually buggy as soon as a trace has real overlaps; people just learned to live with it. So when a bug came in January about overlapping events being broken, I closed it as working-as-intended because I couldn’t see any easy fix from our end.</description><content:encoded>&lt;p&gt;We just
&lt;a href="https://github.com/google/perfetto/releases/tag/v57.1"&gt;released Perfetto v57&lt;/a&gt;
and I wanted to share the new things I&amp;rsquo;m most excited about. This is something I
wanted to do for past releases but I just never quite got round to it. It&amp;rsquo;s also
something I plan on doing more of going forward: there might even be dedicated
pieces if I think the feature deserves it!&lt;/p&gt;
&lt;h2 id="pytorch-traces-reliably-work"&gt;PyTorch traces reliably work!&lt;a class="heading-anchor" href="#pytorch-traces-reliably-work" aria-label="Permalink to PyTorch traces reliably work!"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;What I&amp;rsquo;m most excited about in this release isn&amp;rsquo;t a feature but a bugfix. If you
used the
&lt;a href="https://docs.pytorch.org/tutorials/recipes/recipes/profiler_recipe.html"&gt;PyTorch profiler&lt;/a&gt;
and opened the resulting trace in Perfetto, there was a decent chance some of
your events would just not show up; specifically this would happen when these
events overlapped each other on a single track.&lt;/p&gt;
&lt;p&gt;Technically, PyTorch is in the wrong here. The Chrome Trace Event (JSON) format
says duration events on a track have to nest and can&amp;rsquo;t overlap; if you need
overlap, you&amp;rsquo;re supposed to use async events. &lt;code&gt;chrome://tracing&lt;/code&gt; appears to
handle them, but its rendering is actually buggy as soon as a trace has real
overlaps; people just learned to live with it. So when a
&lt;a href="https://github.com/google/perfetto/issues/4280"&gt;bug&lt;/a&gt; came in January about
overlapping events being broken, I closed it as working-as-intended because I
couldn&amp;rsquo;t see any easy fix from our end.&lt;/p&gt;
&lt;p&gt;Then over time, I realized it wasn&amp;rsquo;t just one person with a weird trace. The bug
had affected many different PyTorch traces, and even
&lt;a href="https://github.com/google/perfetto/issues/6277"&gt;JAX traces&lt;/a&gt;. I even discovered
that people were maintaining forks and hosting old versions of Perfetto just to
deal with this issue. This is basically
&lt;a href="https://www.hyrumslaw.com/"&gt;Hyrum&amp;rsquo;s Law&lt;/a&gt;: it doesn&amp;rsquo;t much matter what the spec
says, once enough people rely on some behaviour, that behaviour is your
contract.&lt;/p&gt;
&lt;p&gt;This is also a very similar situation to what I discussed in
&lt;a href="https://lalitm.com/perfetto-oss-company-prio/"&gt;Perfetto and open source&lt;/a&gt;: it
was genuinely hard for me to tell just how many people it was affecting at the
beginning: if I had understood, I would have dealt with this very differently.&lt;/p&gt;
&lt;p&gt;In any case, in v57, Perfetto now imports the overlapping events instead of
dropping them, overflowing the extras onto a different line in the same UI
track. I do have to credit &lt;a href="https://github.com/i-komarov"&gt;@i_komarov&lt;/a&gt; who helped
me understand how big this issue was and to converge on the fix.&lt;/p&gt;
&lt;h2 id="recording-systemd-journald-logs"&gt;Recording systemd journald logs&lt;a class="heading-anchor" href="#recording-systemd-journald-logs" aria-label="Permalink to Recording systemd journald logs"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Perfetto has always tried to give you as much context as possible about what the
system is doing and put it all on a single timeline. One missing piece of that
on Linux has been in logs from journald; there&amp;rsquo;s a ton of useful information
there but until now it was hard to correlate that with e.g. scheduling or other
app level information.&lt;/p&gt;
&lt;p&gt;With v57, there&amp;rsquo;s now a &lt;code&gt;linux.systemd_journald&lt;/code&gt; data source that records
journald entries straight into the trace, on the same timeline as everything
else. You can filter by minimum syslog priority, by &lt;code&gt;SYSLOG_IDENTIFIER&lt;/code&gt;, or by
systemd unit, so you are not pulling in the entire journal when you only care
about one service.&lt;/p&gt;
&lt;p&gt;To show it in action, here&amp;rsquo;s
&lt;a href="https://ui.perfetto.dev/#!/?url=https://lalitm.com/traces/journald-demo.pftrace"&gt;a trace I recorded on my own machine&lt;/a&gt;.
Alongside a few log lines I generated myself, it happened to capture a real
udisks SMART error that fired while I was recording; exactly the kind of thing
you&amp;rsquo;d otherwise miss.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-v57/journald-logs.png" alt="Journald logs on the Perfetto timeline, with the log panel showing the captured entries including a udisks SMART error"&gt;&lt;/p&gt;
&lt;p&gt;I have to shout out &lt;a href="https://github.com/staticfloat"&gt;@staticfloat&lt;/a&gt; who
contributed this feature; thanks a lot for doing this!&lt;/p&gt;
&lt;h2 id="an-ai-skill-for-recording-and-analysis"&gt;An AI skill for recording and analysis&lt;a class="heading-anchor" href="#an-ai-skill-for-recording-and-analysis" aria-label="Permalink to An AI skill for recording and analysis"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;For a while now, people have been building their own AI tooling around Perfetto.
&lt;a href="https://github.com/Gracker/SmartPerfetto"&gt;SmartPerfetto&lt;/a&gt; and
&lt;a href="https://github.com/antarikshc/perfetto-mcp"&gt;perfetto-mcp&lt;/a&gt; are two public
examples I&amp;rsquo;ve come across but many teams inside Google have built their versions
of these which each handle a subset of Perfetto&amp;rsquo;s functionality. To us, this is
a sign that there&amp;rsquo;s demand out there to build something upstream so that
everyone can benefit.&lt;/p&gt;
&lt;p&gt;v57 includes an installable AI skill that works with Claude Code, Codex, Pi,
Opencode, Antigravity, and anything else that speaks the Agent Skills format. It
explains to the agent how to record traces (Android only for now!) and then
query them. It also includes dedicated workflows for debugging Android memory, a
specific area of focus for us; we plan on expanding these workflows over time
including to Linux.&lt;/p&gt;
&lt;p&gt;The skill is just one piece of a much larger AI plan, which I wrote up as
&lt;a href="https://github.com/google/perfetto/discussions/5763"&gt;an RFC&lt;/a&gt;. We will be doing
much more in this space in the coming months.&lt;/p&gt;
&lt;h2 id="state-tracks"&gt;State tracks&lt;a class="heading-anchor" href="#state-tracks" aria-label="Permalink to State tracks"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;State tracks are a new kind of primitive in Perfetto, sitting alongside slices
and counters. They represent something that is always in exactly one state: a
connection that is open or closed, a device that is on or off, a worker that is
idle or busy. You could already model this with slices, by emitting a slice that
starts when a state begins and ends when it changes. This works but you have to
be careful to emit events &lt;em&gt;exactly&lt;/em&gt; at the same timestamps or you end up having
gaps.&lt;/p&gt;
&lt;p&gt;With a state track you don&amp;rsquo;t emit start and end events at all. At each point
where the state changes, you emit one event that says what the state is now. The
previous state ends automatically. Clearing the track marks it idle. This just
makes it a lot simpler to manage.&lt;/p&gt;
&lt;p&gt;While the simpler emission model is the obvious win, the reason we made it a
first-class primitive goes further than that. Because a state track holds
exactly one value at any moment, it can never overlap itself, and the trace
processor can lean on that guarantee to treat it specially. You can attach
arguments that change as the state does. And in ring-buffer traces, where old
events get overwritten as the buffer wraps, you can periodically re-emit the
current state, so a trace that starts mid-stream still knows what state
everything is in.&lt;/p&gt;
&lt;p&gt;State tracks are still quite new so there are likely to be some rough edges
here, but we think they&amp;rsquo;ll become an important primitive: because they&amp;rsquo;re
guaranteed never to overlap, you can do things with them you simply couldn&amp;rsquo;t
before.&lt;/p&gt;
&lt;h2 id="querying-traces-over-https"&gt;Querying traces over HTTPS&lt;a class="heading-anchor" href="#querying-traces-over-https" aria-label="Permalink to Querying traces over HTTPS"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I recently discovered that quite a few folks have written scripts which download
a trace and then run queries against it with the trace_processor CLI. Which made
me think: why don&amp;rsquo;t we just support that natively inside the CLI itself?&lt;/p&gt;
&lt;p&gt;So in v57, &lt;code&gt;trace_processor&lt;/code&gt; takes an &lt;code&gt;http(s)&lt;/code&gt; URL or a &lt;code&gt;ui.perfetto.dev&lt;/code&gt; share
link directly. It streams the trace and runs your query with no local copy. Here
it is against the journald trace from the previous section:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ trace_processor query \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;https://lalitm.com/traces/journald-demo.pftrace&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;select log_source, count(*) as n from logs where msg is not null group by log_source&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;log_source&amp;#34;,&amp;#34;n&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;systemd_journald&amp;#34;,30
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s one of those small polish features which you wouldn&amp;rsquo;t necessarily think of
immediately but when you have it, you&amp;rsquo;d never want to go back.&lt;/p&gt;
&lt;h2 id="lightning-round"&gt;Lightning round&lt;a class="heading-anchor" href="#lightning-round" aria-label="Permalink to Lightning round"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A few smaller things also landed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shift + mouse wheel scrolls the timeline horizontally.&lt;/strong&gt; A tiny change that
removes a daily papercut when you are panning around a wide trace.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The query results grid got a real overhaul.&lt;/strong&gt; You can sort, reorder, and
hide columns, the sidebar collapses, and SQL errors now show up in the grid
instead of disappearing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Adjacent slices that share a boundary render with a 1px gap,&lt;/strong&gt; so a run of
back-to-back slices reads as separate slices rather than one solid block.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saved textproto record configs are editable,&lt;/strong&gt; saving the trouble of
downloading the config, deleting it, editing it locally, and then reuploading.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="wrap-up"&gt;Wrap up&lt;a class="heading-anchor" href="#wrap-up" aria-label="Permalink to Wrap up"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Overall this was a pretty solid release of Perfetto; it&amp;rsquo;s always satisfying to
fix a bug blocking a lot of people. AI skills and state tracks are both first
steps in a much longer journey, and journald logs are an important new
capability that improves our Linux support. The rest are mostly a bunch of small
quality of life improvements which are always nice to see!&lt;/p&gt;</content:encoded></item><item><title>Perfetto: Swiss Army Knife for Linux Client Tracing</title><link>https://lalitm.com/perfetto-swiss-army-knife/</link><pubDate>Fri, 31 Oct 2025 00:00:00 +0000</pubDate><guid>https://lalitm.com/perfetto-swiss-army-knife/</guid><description>I gave a talk at the 2025 Tracing Summit last month titled “Perfetto: The Swiss Army Knife of Linux Client/Embedded Tracing”. My goal in this talk was to show how Linux kernel, systems and embedded developers can use Perfetto when debugging and root-causing performance issues in their respective domains. Even though the Perfetto UI is primarily built for viewing Android or Chrome traces, it is a flexible tool and can be used in many other ways!
The talk was recorded and is available on YouTube. Taking inspiration from Simon Willison, this post is an annotated presentation containing my slides and detailed notes on them. The talk also has a lot of UI demos: for these, I’ll have a screenshot but also a link to the relevant part of the video (videos are unbeatable for UI!).
First, what is Perfetto? Perfetto is fundamentally a suite of tools: it’s not just one thing but a bunch of different tools working together to help you debug and root-cause problems. This diagram shows how everything fits together, with the core parts of the Perfetto project in the center.
The recording tools for Perfetto consist of 1) an SDK for C++ apps 2) a daemon that can collect data from ftrace, /proc, /sys, and various kernel interfaces 3) another daemon that amalgamates trace data from multiple processes into a single trace file. These tools all speak the Perfetto protobuf format, a high-performance trace format designed to be very efficient to write but not to analyze or consume directly.
That’s where the trace processor comes in. It’s a C++ library that parses the protobuf format, but also a bunch of other widely used trace formats. It exposes this data via an SQL query interface to any embedding program including Perfetto UI (which is what most of this talk is about) and also to the Python API if you want to do ad-hoc scripting or analysis in Python.
There are also very common tracing/profiling formats used by the Linux community: perf.data, ftrace text format, Firefox profiler format, and many others. Perfetto supports quite a few of those directly. There’s also the Chrome JSON format (AKA the Trace Event Format) which is a simpler interchange format. It’s not the most efficient to read or write, but it does the job for a lot of use cases.
Often people write converters. They have their own tracing format, maybe proprietary, maybe open source but something we don’t know about, and it’s very common that people convert to one of the formats we understand, most commonly our protobuf or Chrome JSON formats.
The Perfetto UI is fundamentally a web-based trace visualizer, combining timeline visualization, user-driven selection/aggregation, and SQL queries all in one interface. Because it has the trace processor as a backend, it works with a bunch of different trace formats.
It’s very important to note that even though the Perfetto UI is web-based, everything happens inside your browser and trace data never leaves your system. You can even build it and host it yourself on any static server: we’ve made it extremely easy to do so!
At the start of 2025, we actually moved our whole development to GitHub. In the past, we used to develop on Android and GitHub was just a mirror. That’s no longer the case, GitHub is actually where we develop and take pull requests.
Most of this talk, I’m going to spend actually showing you how you can use the Perfetto UI to debug performance issues on Linux. I don’t want to show you an Android trace which needs a lot of context about how the Android system works and so you think, “oh, that was cool, but I didn’t really understand what was happening.”
So to make this talk more approachable, I wrote a straightforward demo program you can look at yourself! So it’s obviously not a production system but I’ve tried to make it as representative of the sort of issues we use Perfetto for every day.
It’s a Rust program which generates a Julia set and visualizes it over time. The technologies I used: Vulkan, GPU rendering and also multi-threaded CPU computation. So how it works is that computation of various parameters is happening on background threads, and then that’s being passed to the main thread for rendering.
And then, for demonstration purposes, there is a performance bug; rendering should run at 60 FPS, but every so often, the frame rate drops dramatically. Here’s what that looks like:
The code is on GitHub and if you’re interested in following along. The traces are there as well - you don’t have to collect the traces yourself, but you can if you want. All the instructions and information is in the README.
So the first suspicion we may have is that maybe it’s some CPU problem. A lot of engineers I know would reach for perf immediately whenever they see a problem like this. The main reason is that if perf can capture the problem, they can go straight to the line of code without needing to spend time debugging using more complex approaches.</description><content:encoded>&lt;p&gt;I gave a talk at the &lt;a href="https://tracingsummit.org/"&gt;2025 Tracing Summit&lt;/a&gt; last month titled &amp;ldquo;&lt;a href="https://cfp.tracingsummit.org/ts2025/talk/TKVU8W/"&gt;Perfetto: The Swiss Army Knife of Linux Client/Embedded Tracing&lt;/a&gt;&amp;rdquo;. My goal in this talk was to show how Linux kernel, systems and embedded developers can use &lt;a href="https://docs.perfetto.dev"&gt;Perfetto&lt;/a&gt; when debugging and root-causing performance issues in their respective domains. Even though the Perfetto UI is primarily built for viewing &lt;a href="https://perfetto.dev/docs/#why-would-you-use-perfetto-"&gt;Android or Chrome traces&lt;/a&gt;, it is a flexible tool and can be used in many other ways!&lt;/p&gt;
&lt;p&gt;The talk was recorded and is available on &lt;a href="https://www.youtube.com/watch?v=VzTwul2Qb3g"&gt;YouTube&lt;/a&gt;. Taking inspiration from &lt;a href="https://simonwillison.net/"&gt;Simon Willison&lt;/a&gt;, this post is an &lt;a href="https://simonwillison.net/2023/Aug/6/annotated-presentations/"&gt;annotated presentation&lt;/a&gt; containing my slides and detailed notes on them. The talk also has a lot of UI demos: for these, I&amp;rsquo;ll have a screenshot but also a link to the relevant part of the video (videos are unbeatable for UI!).&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%;"&gt;
&lt;iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" src="https://www.youtube.com/embed/VzTwul2Qb3g" title="TS2025 - Perfetto: The Swiss Army Knife of Linux Client/Embedded Tracing" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;p&gt;First, what is Perfetto? Perfetto is fundamentally a suite of tools: it&amp;rsquo;s not just one thing but a bunch of different tools working together to help you debug and root-cause problems. This diagram shows how everything fits together, with the core parts of the Perfetto project in the center.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-03.jpg" alt="diagram of all the pieces of Perfetto, Recording tools, protobuf format, trace processor, Perfetto UI, Python API, Format converters. Chrome JSON, Other profiling formats"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;The recording tools for Perfetto consist of 1) an &lt;a href="https://perfetto.dev/docs/getting-started/in-app-tracing"&gt;SDK for C++ apps&lt;/a&gt; 2) a &lt;a href="https://perfetto.dev/docs/getting-started/system-tracing"&gt;daemon&lt;/a&gt; that can collect data from ftrace, /proc, /sys, and various kernel interfaces 3) another &lt;a href="https://perfetto.dev/docs/concepts/service-model"&gt;daemon&lt;/a&gt; that amalgamates trace data from multiple processes into a single trace file. These tools all speak the Perfetto &lt;a href="https://perfetto.dev/docs/getting-started/converting"&gt;protobuf format&lt;/a&gt;, a high-performance trace format designed to be very efficient to write but not to analyze or consume directly.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s where the &lt;a href="https://perfetto.dev/docs/analysis/trace-processor"&gt;trace processor&lt;/a&gt; comes in. It&amp;rsquo;s a C++ library that parses the protobuf format, but also a bunch of other widely used trace formats. It exposes this data via an SQL query interface to any embedding program including &lt;a href="https://perfetto.dev/docs/visualization/perfetto-ui"&gt;Perfetto UI&lt;/a&gt; (which is what most of this talk is about) and also to the &lt;a href="https://perfetto.dev/docs/analysis/trace-processor-python"&gt;Python API&lt;/a&gt; if you want to do ad-hoc scripting or analysis in Python.&lt;/p&gt;
&lt;p&gt;There are also very common tracing/profiling formats used by the Linux community: perf.data, ftrace text format, Firefox profiler format, and many others. Perfetto &lt;a href="https://perfetto.dev/docs/getting-started/other-formats"&gt;supports&lt;/a&gt; quite a few of those directly. There&amp;rsquo;s also the Chrome JSON format (AKA the &lt;a href="https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview?tab=t.0"&gt;Trace Event Format&lt;/a&gt;) which is a simpler interchange format. It&amp;rsquo;s not the most efficient to read or write, but it does the job for a lot of use cases.&lt;/p&gt;
&lt;p&gt;Often people write &lt;a href="https://perfetto.dev/docs/getting-started/converting"&gt;converters&lt;/a&gt;. They have their own tracing format, maybe proprietary, maybe open source but something we don&amp;rsquo;t know about, and it&amp;rsquo;s very common that people convert to one of the formats we understand, most commonly our protobuf or Chrome JSON formats.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-04.jpg" alt="Slide showing Perfetto UI architecture with web-based trace visualizer features"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;The &lt;a href="https://perfetto.dev/docs/visualization/perfetto-ui"&gt;Perfetto UI&lt;/a&gt; is fundamentally a web-based trace visualizer, combining timeline visualization, user-driven selection/aggregation, and SQL queries all in one interface. Because it has the trace processor as a backend, it works with a bunch of different trace formats.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s very important to note that even though the Perfetto UI is web-based, everything happens inside your browser and trace data never leaves your system. You can even &lt;a href="https://perfetto.dev/docs/contributing/ui-getting-started"&gt;build it&lt;/a&gt; and host it yourself on any static server: we&amp;rsquo;ve made it extremely easy to do so!&lt;/p&gt;
&lt;p&gt;At the start of 2025, we actually moved our whole development to GitHub. In the past, we used to develop on Android and GitHub was just a mirror. That&amp;rsquo;s no longer the case, GitHub is actually where we develop and take pull requests.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-05.jpg" alt="Slide introducing the fractal renderer demo program with Vulkan and multi-threading"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;Most of this talk, I&amp;rsquo;m going to spend actually showing you how you can use the Perfetto UI to debug performance issues on Linux. I don&amp;rsquo;t want to show you an Android trace which needs a lot of context about how the Android system works and so you think, &amp;ldquo;oh, that was cool, but I didn&amp;rsquo;t really understand what was happening.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So to make this talk more approachable, I wrote a &lt;a href="https://github.com/LalitMaganti/fractal-renderer-vk"&gt;straightforward demo program&lt;/a&gt; you can look at yourself! So it&amp;rsquo;s obviously not a production system but I&amp;rsquo;ve tried to make it as representative of the sort of issues we use Perfetto for every day.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a Rust program which generates a Julia set and visualizes it over time. The technologies I used: &lt;a href="https://vulkano.rs/"&gt;Vulkan&lt;/a&gt;, GPU rendering and also multi-threaded CPU computation. So how it works is that computation of various parameters is happening on background threads, and then that&amp;rsquo;s being passed to the main thread for rendering.&lt;/p&gt;
&lt;p&gt;And then, for demonstration purposes, there is a performance bug; rendering should run at 60 FPS, but every so often, the frame rate drops dramatically. Here&amp;rsquo;s what that looks like:&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/test.avif" alt="Animated visualization of Julia set fractal renderer showing frame rate drops"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;The code is on &lt;a href="https://github.com/LalitMaganti/fractal-renderer-vk"&gt;GitHub&lt;/a&gt; and if you&amp;rsquo;re interested in following along. The traces are there as well - you don&amp;rsquo;t have to collect the traces yourself, but you can if you want. All the instructions and information is in the README.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-06.jpg" alt="Slide titled &amp;ldquo;Suspicion #1: Maybe it&amp;rsquo;s a CPU problem?&amp;rdquo; with perf command examples"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;So the first suspicion we may have is that maybe it&amp;rsquo;s some CPU problem. A lot of engineers I know would reach for perf immediately whenever they see a problem like this. The main reason is that if perf can capture the problem, they can go straight to the line of code without needing to spend time debugging using more complex approaches.&lt;/p&gt;
&lt;p&gt;You can record a perf profile with &lt;code&gt;perf record -k mono -g ./fractal_renderer&lt;/code&gt;. The standard post-processing step which I think a lot of people do would be to &lt;a href="https://github.com/brendangregg/FlameGraph"&gt;generate&lt;/a&gt; an SVG flame graph out of this with &lt;code&gt;perf script | stack-collapse-perf.pl --all | flamegraph.pl &amp;gt; fractal-frame.svg&lt;/code&gt;. Here&amp;rsquo;s how that looks like for our perf profile:&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/fractal.svg" alt="Interactive flame graph showing CPU profiling data with thread names and function call stacks dominated by cos and sin operations"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;See also the &lt;a href="https://lalitm.com/img/fractal.svg"&gt;interactive version of the profile&lt;/a&gt;&lt;/center&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The flame graph shows the thread names at the bottom, and then stacked above are the call stacks of what the program is doing. The width represents how much time is spent in each function. In this case, the worker threads are spending most of their time in &lt;code&gt;cos&lt;/code&gt; and &lt;code&gt;sin&lt;/code&gt; operations, doing math computation. Exactly what you&amp;rsquo;d expect for this type of program. &lt;em&gt;Aside: Interestingly demangling didn&amp;rsquo;t seem to work for Rust out of the box which I find a bit unusual but I didn&amp;rsquo;t dig too much into why this was.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Looking at this, nothing really stands out. There&amp;rsquo;s no smoking gun that immediately reveals the problem. But here&amp;rsquo;s the fundamental limitation: the flame graph aggregates data across the entire trace, losing the time dimension. The performance problem we&amp;rsquo;re seeing happens every 2-3 seconds - brief drops in an otherwise normally functioning program.&lt;/p&gt;
&lt;p&gt;The flame graph shows me the aggregate, dominated by the correct behavior, making it nearly impossible to spot those occasional problematic moments. So how do I find the places where it&amp;rsquo;s doing the wrong thing?&lt;/p&gt;
&lt;p&gt;Well, that&amp;rsquo;s maybe where Perfetto can help you out a little bit! The thing I find lots of people don&amp;rsquo;t know is that perf actually &lt;em&gt;preserves&lt;/em&gt; timestamp information about when samples were taken: many tools drop this information but Perfetto is pretty good at showing that to you. I just need post-process the trace with &lt;code&gt;perf script &amp;gt; fractal.perftext&lt;/code&gt; to generate a text version of the profile which we can then open in the &lt;a href="https://ui.perfetto.dev"&gt;Perfetto UI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;My demo talking through how to open the perf profile and navigate it starts at &lt;a href="https://youtu.be/VzTwul2Qb3g?t=551"&gt;9:11&lt;/a&gt; in the video.&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot3.png" alt="Perfetto UI screenshot showing perf profile timeline with thread tracks and CPU sample markers across time axis"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=590"&gt;9:50&lt;/a&gt; in the video&lt;/center&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The x-axis of what you&amp;rsquo;re seeing is time. And every horizontal line represents a thread: we call these lanes &amp;ldquo;tracks&amp;rdquo;. And each of the small arrowheads on the tracks are CPU samples for the associated thread.&lt;/p&gt;
&lt;p&gt;The behavior of the worker threads over time is really interesting. Most of the lifetime of the program, it&amp;rsquo;s doing continuous computation, basically. And then there&amp;rsquo;s this period of time in the middle where there&amp;rsquo;s this very interesting staircase pattern where it seems like only one thread is running at any one time: we&amp;rsquo;ll want to keep a note of this as this is quite important.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot4.png" alt="Perfetto UI screenshot demonstrating area selection feature with timeline selection and flame graph visualization below"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=637"&gt;10:37&lt;/a&gt; in the video&lt;/center&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;One very cool thing about Perfetto is that it allows me to quickly generate visualizations of whatever I&amp;rsquo;m selecting on the timeline. We call this &amp;ldquo;area selection&amp;rdquo; and it&amp;rsquo;s where I drag my mouse and select a region both horizontally and vertically. This is on one track but even &lt;em&gt;across&lt;/em&gt; multiple tracks. So in the timeline it shows me the selection I&amp;rsquo;m making at the top, plus a flame graph at the bottom representing the aggregation of the samples in just that time period.&lt;/p&gt;
&lt;p&gt;The key advantage is that I can look at individual regions of time interactively. You can also do this with &lt;code&gt;flamegraph.pl&lt;/code&gt; but you need to pre-filter the data to what you&amp;rsquo;re looking for. This assumes you already know what the problem is before you find it. I always find that a bit counterintuitive. I prefer this view where I can see everything first, then decide &amp;ldquo;I want to look at this specific part in more detail.&amp;rdquo; That&amp;rsquo;s what Perfetto lets me do.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot5.png" alt="Perfetto UI screenshot showing enhanced flame graph with zoom, frame hiding, regex search, and bottom-up view features"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=751"&gt;12:31&lt;/a&gt; in the video&lt;/em&gt;&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;So now on to the flame graph itself: in the last year, I spent a bunch of time on improving the flame graph visualization in Perfetto UI. At Google, we have an internal tool called pprof (related to but not the same as the open-source one), and I&amp;rsquo;ve always loved the visualization it has. So I worked to make Perfetto&amp;rsquo;s flame graph look and behave very similarly.&lt;/p&gt;
&lt;p&gt;There are a bunch of features here. You can zoom in like most flame graph, but you can also say &amp;ldquo;I only want to look at the stack starting from this point&amp;rdquo; — it gets rid of everything above and starts fresh from there. If I don&amp;rsquo;t want to see a particular function like &lt;code&gt;sin&lt;/code&gt;, I can just hide the frame and it gets merged into its parent. The search is regex-based so I can also just type the specific things I&amp;rsquo;m interested in: it&amp;rsquo;s pretty powerful.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s also something I don&amp;rsquo;t think I&amp;rsquo;ve seen in other visualizers (I might be wrong, please do correct me!): what I call &amp;ldquo;bottom up&amp;rdquo; view. Imagine you take all the leaves across your entire program and visualize who&amp;rsquo;s calling into them. If you have a leaf function that&amp;rsquo;s called everywhere in your program but reached from many different places, it&amp;rsquo;ll be split across your flame chart. This is the inverse — you&amp;rsquo;re looking at the leaves and asking &amp;ldquo;who is calling me?&amp;rdquo; This is particularly useful when you&amp;rsquo;re trying to optimize very low-level functions that are always at the leaf level — things like memcpy or hashmap operations.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-07.jpg" alt="Slide titled &amp;ldquo;Suspicion #2: Sleeping on what?&amp;rdquo; discussing need for scheduler trace analysis"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;So our main takeaway is that our worker threads all had gaps in their CPU execution in a staircase pattern. This means the threads weren&amp;rsquo;t actually on the CPU and that&amp;rsquo;s usually a sign that they&amp;rsquo;re sleeping.&lt;/p&gt;
&lt;p&gt;But sleeping on what? Locks? Disk? Network? What exactly is happening? To answer that, I need a scheduler trace to show me the wake-up patterns, who&amp;rsquo;s being scheduled when, what type of sleep threads are in, that sort of thing.&lt;/p&gt;
&lt;p&gt;We recently added support for trace-cmd&amp;rsquo;s text format in Perfetto (&lt;em&gt;aside: &lt;a href="https://github.com/google/perfetto/issues/1819"&gt;there&amp;rsquo;s&lt;/a&gt; an open issue to support the binary format too!&lt;/em&gt;). For this demo, I&amp;rsquo;m collecting sched_switch and sched_waking events with &lt;code&gt;sudo trace-cmd record -e sched:sched_switch -e sched:sched_waking -C mono ./fractal-renderer-vk&lt;/code&gt; and we can open it in the UI once we do &lt;code&gt;trace-cmd report -N &amp;gt; fractal.sched&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The demo showing off scheduler traces starts at &lt;a href="https://youtu.be/VzTwul2Qb3g?t=916"&gt;15:16&lt;/a&gt; in the video.&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot6.png" alt="Perfetto UI screenshot showing scheduler trace with CPU scheduling tracks at top, white regions indicating idle time"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=950"&gt;15:49&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;So this is what a scheduler trace looks like. Again as before, the x-axis is time. At the top of the trace, you&amp;rsquo;ve got the CPU scheduling tracks. For each CPU, they tell us what was scheduled on that CPU at each point in time. The white regions are where there&amp;rsquo;s nothing scheduled. As I zoom in, you start to see information like the name of the thread that&amp;rsquo;s scheduled, the TID of the thread, and so on. This is the CPU view of things, looking at it from a CPU perspective.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot7.png" alt="Perfetto UI screenshot showing thread state tracks with dark green for running, light green for runnable, and white for interruptible sleep"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1008"&gt;16:48&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;There&amp;rsquo;s also a thread perspective on scheduling: what we call this &amp;ldquo;thread state&amp;rdquo;. This shows the scheduling state of each thread at every point in time. Dark green represents the thread running, light green represents runnable (the thread is on the runqueue so it&amp;rsquo;s eligible to run, but the scheduler hasn&amp;rsquo;t actually let it run yet), and white represents interruptible sleep (S sleep). There are also orange regions for uninterruptible sleep (D sleep), though that doesn&amp;rsquo;t show up much in this trace.&lt;/p&gt;
&lt;p&gt;You can again see a very clear staircase-like pattern. Again, only one thread seems to be running at any one time. You&amp;rsquo;re maybe getting the sense of what the problem might be at this point.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot8.png" alt="Perfetto UI screenshot showing area selection on CPU track with tables displaying time spent by each thread"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1063"&gt;17:43&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;Like with the perf visualization, you can do area selections here too. I can select a region on a CPU and get tables showing time spent by each thread (shown in the screenshot above). I can also do this for thread state, you can also see that runnable time is basically negligible compared to running and sleeping, which is where most of the time is being spent.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot9.png" alt="Perfetto UI screenshot showing scheduler visualizations including run queue length and active CPU count metrics"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1092"&gt;18:12&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;There are also scheduler-specific visualizations like run queue length and active CPU count. You can see in the problematic region, the active CPU count also went down, which makes sense.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-08.jpg" alt="Slide titled &amp;ldquo;Suspicion #3: What is the program doing?&amp;rdquo; discussing need for application-level visibility"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;So the scheduler trace shows when threads are sleeping, but it&amp;rsquo;s not telling us why. What was the program doing in that region? What code was it running? The sequential pattern suggests some sort of serialization—something is causing only one thread to run at a time. But we need application-level visibility.&lt;/p&gt;
&lt;p&gt;Since this program was written in Rust, I just used the off-the-shelf &lt;a href="https://docs.rs/tracing/latest/tracing/"&gt;&lt;code&gt;tracing&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.rs/tracing-perfetto/latest/tracing_perfetto/"&gt;&lt;code&gt;tracing-perfetto&lt;/code&gt;&lt;/a&gt; crates; I did have to make some small &lt;a href="https://github.com/LalitMaganti/tracing-perfetto"&gt;modifications&lt;/a&gt; to tracing-perfetto that I&amp;rsquo;m hoping to upstream. These output a Perfetto trace without needing to use the Perfetto SDK. These libraries are also maintained by others: we don&amp;rsquo;t have any hand in them.&lt;/p&gt;
&lt;p&gt;All I needed to do was integrate these into my program and then add a command line switch to write out the collected trace to a file. So I just do &lt;code&gt;./fractal_renderer --trace fractal.pftrace&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;My demo for app tracing starts at &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1177"&gt;19:37&lt;/a&gt; in the video.&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot10.png" alt="Perfetto UI screenshot showing app trace with userspace instrumentation slices on thread tracks representing program activity"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1206"&gt;20:06&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;Looking at the app trace: as before x-axis is time and each of the tracks represents a thread. Instead of scheduling activity or CPU stack samples, this time the tracks is userspace instrumentation of the program itself. Each of these rectangles is a named period of time representing what the program was doing at that time.&lt;/p&gt;
&lt;p&gt;There are lots of different names for these in the tracing world (e.g. spans, intervals) but we call these &amp;ldquo;slices&amp;rdquo;. The main thread is rendering frames as you would expect and the workers are each computing tiles of that frame, which eventually feed back to the main thread and sync to the GPU.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot11.png" alt="Perfetto UI screenshot showing flow visualization with causal links between render frame and worker thread operations"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1425"&gt;23:42&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;There&amp;rsquo;s also this thing called flows, which shows the causal links between different pieces. Render frame is calling into all these places and causing them to happen. It&amp;rsquo;s sort of similar to wakeup graphs but for user space: basically, this is what caused me to start running this function.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot12.png" alt="Perfetto UI screenshot zoomed into problematic region showing 1.8 second duration for update adaptive quality operation"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1431"&gt;23:51&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;So you can see very clearly there&amp;rsquo;s a normal region and then a region where things are taking 1.8 seconds: almost certainly the cause of the frame drops.&lt;/p&gt;
&lt;p&gt;And if we look at the slice in question, it seems to be doing something called &amp;ldquo;update adaptive quality.&amp;rdquo; Basically, I wrote some code to dynamically change the rendering quality based on frame rate. If I&amp;rsquo;m running faster, I can render at higher quality. If I&amp;rsquo;m running slower, I can do lower quality. That&amp;rsquo;s what this adaptive quality thing is supposed to do.&lt;/p&gt;
&lt;p&gt;But clearly something has gone wrong. I&amp;rsquo;m causing frame drops because of updates to adaptive quality. A little bit ironic, to say the least. Now we know what the program is actually doing during that time span.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-09.jpg" alt="Slide titled &amp;ldquo;Putting it all together: The merged trace&amp;rdquo; explaining trace merging feature"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;So now we&amp;rsquo;ve looked at three different sources of debugging data separately. In perf, we got told there are few or no CPU samples and weird staircase patterns. In ftrace, we saw only one worker seems to be active and the rest are sleeping in interruptible sleep. And in app tracing, we see it&amp;rsquo;s because of adaptive quality updates that workers are working on, and they shouldn&amp;rsquo;t be doing it this way.&lt;/p&gt;
&lt;p&gt;Obviously, the theory is that it&amp;rsquo;s all the same problem. But we can confirm this theory with a very new (and still experimental) feature of the UI: trace merging.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: as this part of Perfetto is still experimental, if you want to try it yourself, you need to go to plugins and enable the &amp;ldquo;MultiTraceOpen&amp;rdquo; plugin. Also, unlike I what say in the talk, you do &lt;strong&gt;not&lt;/strong&gt; need to be on Autopush as all the features I showed in my talk are now available in Stable.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The demo showing off merged traces starts at &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1472"&gt;24:32&lt;/a&gt; in the video.&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot13.png" alt="Perfetto UI screenshot showing merged trace with CPU scheduling tracks, stack samples, and app instrumentation on single timeline"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1544"&gt;25:44&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;This is now the merged trace file containing all the different information. You can see the CPU scheduling tracks like we had in the scheduler trace, the stack samples like we had in the perf trace, and the app instrumentation, all beside each other on one timeline.
You can very clearly see the adaptive quality update running, then this period where it ran, and then it was done. It&amp;rsquo;s very cool to be able to see the pattern of how my program is sleeping and where and what it was running on one timeline.&lt;/p&gt;
&lt;p&gt;The thing is, you&amp;rsquo;ve always been able to do this with Perfetto if you collect a Perfetto trace with all of these integrated. The new capability is that this is now being brought to traces you didn&amp;rsquo;t collect with Perfetto. Collect it with whatever you like, and we&amp;rsquo;ll still manage to do this visualization. That&amp;rsquo;s the new capability we have.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot14.png" alt="Perfetto UI screenshot showing query interface with pivot tables and filter options for trace data analysis"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1798"&gt;29:58&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;There&amp;rsquo;s also a query interface which we&amp;rsquo;ve been building out recently and there are some pretty powerful things you can do with these tables. As well as the flat tables of data, there&amp;rsquo;s also a more dynamic pivot table and if I click the arrow on the left, I can get into a detailed filter table, similar to a spreadsheet but optimize for things people want to do on traces.&lt;/p&gt;
&lt;p&gt;For example, by doing an area select, I can first get a list of all the events that happened during a time region. Then using the table I can filter for things - say I only care about slices longer than some duration, like 319 microseconds for whatever reason. I can click and add a filter for things greater than this.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/screenshot15.png" alt="Perfetto UI screenshot demonstrating Show Debug Track feature with filtered events visualized as timeline track"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot from &lt;a href="https://youtu.be/VzTwul2Qb3g?t=1811"&gt;30:11&lt;/a&gt; in the video&lt;/em&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;There&amp;rsquo;s also a feature called &amp;ldquo;Show Debug Track&amp;rdquo; that&amp;rsquo;s also very powerful. The table shows rows with timestamped duration information, and this feature lets you visualize that data as a track on the timeline. It adds a track at the top showing the regions of time where these events happened—in this case, where ComputeTile took longer than a certain threshold.&lt;/p&gt;
&lt;p&gt;This is particularly useful for correlation analysis. For example, in Android, we&amp;rsquo;re often looking at system A and trying to understand its effect on system B. We find all the places where one thing is slow, then look for correlations. Being able to see a track in the UI where you can quickly have context and say &amp;ldquo;oh, during this period of time, this other thing was happening&amp;rdquo; is invaluable. It&amp;rsquo;s probably one of our most-used features.&lt;/p&gt;
&lt;p&gt;You can also copy the SQL query from these tables and start doing your own aggregations on top of it. This eases the burden of starting with a completely blank canvas. Instead of wondering &amp;ldquo;where do I even start querying my data? What tables is my data in?&amp;rdquo;, the UI gives you a starting query that you can build on without needing to write something from scratch.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-10.jpg" alt="Slide titled &amp;ldquo;The root cause&amp;rdquo; summarizing findings about dynamic quality updates causing frame drops"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;So the dynamic quality updates were stopping the world. Perf profiling showed the problem, scheduler traces found the sleeping pattern, app tracing confirmed it was the quality adjustment code, and the single timeline view let me see everything happening at once.&lt;/p&gt;
&lt;p&gt;Interestingly, I tried to fix this by removing the lock contention—which I thought was the bug I had introduced. But it turns out I shouldn&amp;rsquo;t have been doing this code in the workers in the first place. Even after removing the lock contention, just the CPU activity of doing that work was enough to cause frame drops. The right solution was to move it to a background thread. As part of debugging this for the demo, I discovered something even better that I could be doing.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-11.jpg" alt="Slide titled &amp;ldquo;Perfetto in the Open-Source Community&amp;rdquo; listing projects using Perfetto including Mesa, VizTracer, pthread_trace, magic-trace, sched-analyzer, and systing"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.perfetto.dev"&gt;Android and Chrome&lt;/a&gt; are our bread and butter—that&amp;rsquo;s what we officially support as a team, and why Google staffs us. But there are many other interesting uses.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.mesa3d.org/perfetto.html"&gt;Mesa&lt;/a&gt; uses Perfetto as one of its tracing systems. One thing I could have shown is collecting a Mesa trace alongside all the other traces we looked at—you can actually see what the GPU is doing at the same time, which would have been very cool, but I just didn&amp;rsquo;t have time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/gaogaotiantian/viztracer"&gt;VizTracer&lt;/a&gt; is function tracing for Python, similar to uftrace, but you don&amp;rsquo;t have to recompile anything or do anything special.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/dsharlet/pthread_trace"&gt;pthread_trace&lt;/a&gt; is for visualizing pthread mutex contention. The author has a very efficient way of doing this and writes protobuf using heavy use of constexpr to make it very low overhead. It&amp;rsquo;s a very interesting project.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/janestreet/magic-trace"&gt;magic-trace&lt;/a&gt; uses Intel Processor Trace for function-level tracing at the processor level with lower overhead. They wrote a converter from that to the Perfetto format so you can visualize that data in Perfetto.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/qais-yousef/sched-analyzer"&gt;Qais Yousef&amp;rsquo;s sched-analyzer&lt;/a&gt; enriches Perfetto traces with scheduler internals. It&amp;rsquo;s a very cool project that I find particularly interesting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/johnstultz-work/0ec4974e0929c4707bfd89c876ae4735"&gt;John Stultz&amp;rsquo;s all-in-one Perfetto recording script&lt;/a&gt; for kernel developers addresses a common complaint: &amp;ldquo;Perfetto is so complicated, I don&amp;rsquo;t know what events I want to record.&amp;rdquo; He just wrote a script that configures everything for you.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, &lt;a href="https://josefbacik.github.io/kernel/systing/debugging/2025/05/08/systing.html"&gt;Josef Bacik&amp;rsquo;s systing&lt;/a&gt; is a bit experimental but fascinating. He re-implemented tracing daemons on top of BPF instead of Perfetto&amp;rsquo;s native implementation, combining BPF-based tracing with perf stack traces in a single binary. He has a blog post explaining why. I thought it was a fascinating use of Perfetto.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-12.jpg" alt="Slide encouraging users to try the demo program and record their own traces"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;If you want to try this yourself, you can use the &lt;a href="https://github.com/LalitMaganti/fractal-renderer-vk"&gt;demo program I&amp;rsquo;ve provided&lt;/a&gt;. But even better: record traces on your own programs. Open scheduler traces and perf at the same time. Instrument your program, convert it to Perfetto format, and visualize everything together.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-13.jpg" alt="Slide promoting comprehensive tutorial for converting ad-hoc timestamped data to Perfetto format"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;If you want to convert ad-hoc timestamped data to Perfetto, we wrote a &lt;a href="https://perfetto.dev/docs/getting-started/converting"&gt;comprehensive tutorial&lt;/a&gt; with Python snippets for everything you might want to visualize. It covers all the features I showed and how to write Python code to generate them. We have a library for writing these traces: besides this one library, you don&amp;rsquo;t need to install anything else. You can go ahead and convert your own data to Perfetto.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-14.jpg" alt="Slide welcoming contributions and pull requests to the Perfetto project"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;We&amp;rsquo;re very happy to accept contributions and review pull requests pretty quickly. We&amp;rsquo;ve had a lot of open-source contributors over the years and have been quite lucky with some very high-quality contributions. If you want to contribute yourself or have a feature you feel is missing, send it our way.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://lalitm.com/img/perfetto-swiss-army-15.jpg" alt="Final slide with contact information and links to demo repo, documentation, and Perfetto UI"&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Demo repo: &lt;a href="https://github.com/LalitMaganti/fractal-renderer-vk"&gt;github.com/LalitMaganti/fractal-renderer-vk&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Learn more: &lt;a href="https://docs.perfetto.dev"&gt;docs.perfetto.dev&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Perfetto UI: &lt;a href="https://ui.perfetto.dev"&gt;ui.perfetto.dev&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Contact: &lt;a href="mailto:lalitm@google.com"&gt;lalitm@google.com&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>