What is System Tracing A Guide to Developer Options

When it comes to diagnosing complex performance problems in an Android application—like stuttering animations (jank), slow startup, or unexplained power drain—simple logging is often not enough. You need a way to see a holistic, high-fidelity view of exactly what your app and the entire Android system were doing over a short period of time. The most powerful tool for this job is System Tracing. It’s a low-overhead tool that records device activity over a short period and presents it as a detailed, interactive timeline report that lets you analyze everything from CPU scheduling and thread states to application rendering and I/O operations.

The Problem: Understanding System-Wide Performance

An Android application does not run in a vacuum. Its performance is deeply intertwined with the behavior of the underlying operating system. A smooth user experience requires your app’s code to run at the right time, on the right CPU core, without being preempted by other system processes.

Trying to debug performance issues with isolated tools can be misleading:

  • Logcat is good for seeing discrete events but provides no sense of duration or system-wide context.
  • A CPU Profiler can tell you which of your app’s methods are consuming CPU time, but it won’t tell you if your app’s thread was put to sleep by the kernel scheduler to make way for another process.
  • Memory Profilers show memory allocation but don’t explain latency caused by I/O waits or resource contention.

To solve issues like animation stutter, you need to answer complex questions like: “Why did my app’s UI thread not run for 50 milliseconds, causing it to miss two frames? Was it busy doing too much work, was it blocked waiting for a disk read, or was it put to sleep by the kernel?” Answering these questions requires a system-level view.

Introducing System Tracing: A Timeline of Everything

System Tracing captures a precise timeline of events from the Android kernel, system services, and your application’s code. It hooks into the Linux kernel’s `ftrace` mechanism and Android’s own `atrace` framework to record what every process and thread is doing at a microsecond level of detail. The output is a large HTML file that can be opened in a browser-based viewer (like the open-source Perfetto UI) for analysis.

This trace report provides a wealth of information, visualized as a series of tracks on a common timeline:

  • CPU Core Activity: Shows which process was running on each CPU core at any given moment. This is crucial for identifying CPU bottlenecks and scheduling issues.
  • Thread States: For each process, it shows the state of every thread (Running, Runnable, Sleeping, Blocked) over time. This lets you see exactly when and why your app’s main thread was not running.
  • Application Tracepoints: Developers can add custom trace events to their own code (`Trace.beginSection(“My-Work”)`), which will appear in the timeline. This allows you to measure the duration of specific operations in your app.
  • System Service Events: It captures events from critical system services like SurfaceFlinger (for UI composition), ActivityManager, and the hardware composer.

How to Capture a System Trace

There are several ways to capture a system trace, but the most common methods for developers are the on-device tool and Android Studio.

1. On-Device System Tracing (Developer Options)

This is the easiest way to get started. It’s a feature available directly on the device.

  1. Enable Developer Options on your Android device.
  2. Go to Settings > Developer options > System Tracing.
  3. Configure the trace settings. You can select which categories of events to record (e.g., `gfx` for graphics, `view` for the View system, `sched` for CPU scheduling).
  4. Enable the “Trace debuggable applications” toggle to include your app’s custom tracepoints.
  5. Tap the “Record trace” button.
  6. Perform the action in your app that you want to profile (e.g., scroll through a list that stutters).
  7. Pull down the notification shade and tap the “Stop tracing” notification.
  8. The system will save the trace as a `.perfetto-trace` or `.ctrace` file, which you can then share to your computer for analysis.

2. Android Studio CPU Profiler

For more integrated analysis, you can use the profiler built into Android Studio.

  1. Run your app on a device or emulator.
  2. Open the Profiler window in Android Studio (View > Tool Windows > Profiler).
  3. Select the CPU timeline.
  4. Choose the System Trace configuration.
  5. Click Record, perform the actions in your app, and then click Stop.
  6. Android Studio will capture and immediately display the trace within its own built-in viewer, correlating the system events with your app’s threads and methods.

Analyzing a System Trace: A Practical Example

The trace viewer can look complex, but focusing on a few key areas can yield powerful insights. Imagine you are debugging a stuttering animation.

You would look for a “slice” on the timeline that corresponds to a single, long frame (e.g., one that took 33ms instead of the expected 16.67ms).

In the trace for that long frame, you would examine the row for your app’s UI Thread (or Main Thread). You might see one of several patterns:

  • Long Green Slice: The thread state is green (“Running”). This means your code was actively running on a CPU core for too long. You would then zoom in on the application tracepoints within that green slice to see which part of your code is the bottleneck.
  • White or Gray Slice: The thread state is white (“Sleeping”). This means your UI thread was blocked, waiting for another operation to complete. Often, this is caused by doing disk I/O or a long-running network request on the main thread, which is a major performance anti-pattern.
  • Orange Slice: The thread state is orange (“Runnable”). This is the most subtle case. It means your thread was ready and able to run, but the kernel’s CPU scheduler had not scheduled it to run on a CPU core, likely because other, higher-priority threads were running instead. This can help you identify resource contention issues.

By analyzing these patterns, you can quickly move from “the app is slow” to a precise diagnosis like “the UI thread was blocked for 25ms waiting for a database query on frame #1234.” For an in-depth guide on analysis, the official Android Developer documentation on tracing is essential reading.

Frequently Asked Questions

What is the difference between System Tracing and Method Tracing?

They are two different profiling techniques that answer different questions.

  • System Tracing (`atrace`/Perfetto): Has very low overhead. It tells you *when* your code ran and for how long, in the context of the entire system. It’s best for diagnosing stutter and scheduling issues.
  • Method Tracing (`Debug` API): Has very high overhead and significantly slows down the app. It tracks the entry and exit of every single method in your code. It’s best for understanding *what* your code is doing in a micro-level, algorithmic sense (e.g., which function is calling which other function), but it’s not suitable for analyzing real-time performance issues like jank because its overhead distorts the timing.

The general advice is to always start with a system trace.

What is Perfetto?

Perfetto is the next-generation, open-source tracing project that is now the default for system tracing in Android (since Android 10). It replaces the older `systrace` and `atrace` systems. It provides more detailed data, a more powerful and interactive web-based UI for analysis, and is the foundation for all modern system performance analysis on Android.

Can System Tracing be used to analyze power consumption?

Yes. Modern system trace configurations can include power-related categories, such as CPU frequency scaling and battery drain counters. By correlating spikes in power draw with the CPU activity shown in the trace, you can identify which specific processes and threads are responsible for waking up the device and consuming energy.

Does adding custom trace events slow down my app?

The overhead of adding custom trace events (`Trace.beginSection`) is extremely low. When tracing is not active, the call to the trace function is almost a no-op and has a negligible performance impact. It is considered safe and is highly encouraged to generously instrument your application’s code with trace events to make future performance analysis much easier.