CN

Android Systrace Basics - Prerequisites for Analyzing Systrace

Word count: 2.5kReading time: 15 min
2019/07/23
loading

Technical update — 2026-10-13: Historical Systrace screenshots are retained, including cases added after the original 2019 article. Colors and shortcuts refer to the legacy UI. Linux state semantics are checked against v6.6 documentation; the modern UI reference is Perfetto v58.3 (11fbaed83). Inaccurate Self Time, wakeup and scheduling-state annotations in the images are corrected in the adjacent text. These are not new device measurements.

This is the second article in the Systrace series, primarily explaining the prerequisites for analyzing Systrace. With these prerequisites, analyzing Systrace will be more effective, allowing you to identify issues faster and more efficiently.

This article introduces how to view thread states in Systrace, how to analyze thread wakeup information, how to interpret data in the information panel, and common shortcuts. By studying this article, you will gain an understanding of process and thread-related information and know how to extract key information from complex Systrace traces.

Table of Contents

Series Article Index

  1. Introduction to Systrace
  2. Systrace Basics - Prerequisites for Systrace
  3. Systrace Basics - Why 60 fps?
  4. Android Systrace Basics - SystemServer Explained
  5. Systrace Basics - SurfaceFlinger Explained
  6. Systrace Basics - Input Explained
  7. Systrace Basics - Vsync Explained
  8. Systrace Basics - Vsync-App: Detailed Explanation of Choreographer-Based Rendering Mechanism
  9. Systrace Basics - MainThread and RenderThread Explained
  10. Systrace Basics - Binder and Lock Contention Explained
  11. Systrace Basics - Triple Buffer Explained
  12. Systrace Basics - CPU Info Explained
  13. Systrace Smoothness in Action 1: Understanding Jank Principles
  14. Systrace Smoothness in Action 2: Case Analysis - MIUI Launcher Scroll Jank Analysis
  15. Systrace Smoothness in Action 3: FAQs During Jank Analysis
  16. Systrace Responsiveness in Action 1: Understanding Responsiveness Principles
  17. Systrace Responsiveness in Action 2: Responsiveness Analysis - Using App Startup as an Example
  18. Systrace Responsiveness in Action 3: Extended Knowledge on Responsiveness
  19. Systrace Thread CPU State Analysis Tips - Runnable
  20. Systrace Thread CPU State Analysis Tips - Running
  21. Systrace Thread CPU State Analysis Tips - Sleep and Uninterruptible Sleep

Main Content

Reading This Article with Perfetto

This article builds the basic skills needed before analyzing a trace: thread states, wakeup relationships, information-panel fields, and navigation shortcuts. The old Systrace UI and the current Perfetto UI look different, but these skills remain the same foundation.

In the old flow, Systrace HTML used colors to show thread states directly, and clicking a slice exposed fields such as duration, thread, process, and wakeup information in the lower panel. In the current flow, Perfetto spreads the same evidence across thread tracks, CPU scheduling tracks, the selection panel, search results, and SQL tables. The workflow changes from “read one HTML view” to “read tracks first, then narrow evidence with search or SQL.”

Use this mapping while reading:

Topic in this article Perfetto entry point
Opening, zooming, searching, selecting slices Perfetto 3: Perfetto View
Running, Runnable, Sleep, and similar thread states Perfetto 9: CPU information
Main-thread waits, RenderThread waits, Binder waits Perfetto 7: MainThread and RenderThread / Perfetto 10: Binder scheduling and lock contention

Viewing Thread States

When scheduling data is captured, legacy Systrace uses thread-state strips to help interpret slices. A slice is an instrumented interval, not necessarily an entire method. States narrow an investigation; they do not by themselves prove that Binder, a lock, I/O or CPU execution is the root cause. The colors below refer to the historical images. Read the State field and underlying events rather than relying on color alone.

When using Perfetto for the same problem today, do not look only for colors that match the old Systrace UI. A more reliable method is to read three signals together: slices on the thread track, actual running intervals on CPU tracks, and scheduling states such as Runnable, Sleep, and Uninterruptible Sleep. That is how you separate “the function itself is slow,” “the thread woke up but did not get CPU,” and “the thread is waiting for Binder, a lock, or I/O.”

Main thread states include:

Green: Running

The viewer shows a thread scheduled on a logical CPU during this interval, not merely ready and queued. Linux TASK_RUNNING and the R shown by ps include both executing and runnable tasks; the viewer distinguishes these using scheduling events. One thread cannot execute on two logical CPUs simultaneously, though it can migrate between intervals.

We often compare Running time for the same scenario: why is it faster here and slower there? Is the frequency different, is it running on another core, or is it repeatedly switching between Running, Runnable and Sleep? Read those clues alongside the CPU topology and scheduling events. A small core or lower frequency is not inherently a scheduling error; consider workload, power policy, thermals and the critical path. The image shows android.bg Running on CPU 0 for 41.743 ms. That describes this interval, not an entire method or the whole process.

Blue: Runnable

The thread is eligible to run but is not currently executing on a CPU. It may have been awakened or preempted. Delay depends on its allowed CPUs, priority, scheduling class, CPU quotas/throttling and competing work.

A long Runnable interval suggests scheduling latency, not necessarily that every CPU is busy, frequency is too low or too many background apps exist. Inspect the CPUs the thread may use, what they were running, and evidence of throttling, preemption or wakeup migration.

White: Sleep

This usually means interruptible sleep while awaiting an event, timer, Binder activity or synchronization condition. It can be healthy idleness or a critical-path wait for a result. Waiting does not imply there is no work left to complete.

The image shows audioserver’s Binder:1506_2 Sleeping at binder_thread_read. This is a clue about waiting for Binder-related events, not proof of mutex contention or a performance fault.

Orange: Uninterruptible Sleep - IO Block

The image’s State is Uninterruptible Sleep | WakeKill - Block I/O, and the displayed blocked function is wait_on_page_bit_killable, not the original text’s wait_on_page_locked_killable. Scheduling events and additional blocked-reason/I/O-wait data contribute to this interpretation. Availability depends on the kernel, permissions and recording configuration.

Investigate page-related waiting alongside faults, reclaim, storage requests and blocked stacks. Cold file reads, page locking or memory pressure may contribute; neither orange coloring nor this function name proves low memory or a busy disk. WakeKill also matters: “uninterruptible” does not mean every signal is always ineffective. Linux killable waits include wakeup by fatal signals.

Purple: Uninterruptible Sleep

This image explicitly says Uninterruptible Sleep. That does not mean “usually memory management,” nor simply that execution entered kernel mode. A thread executing a system call can still be Running. Uninterruptible waits may involve drivers, synchronization or other kernel resources; investigate the actual blocked location.

The pictured thread is [crtc_commit:127], with display-composition tracks nearby. Do not classify this as low memory from the color. Legacy viewers also reuse similar colors for other states, so inspect the State field.

Analyzing Thread Wakeup Information

Systrace identifies a very useful piece of information that helps us analyze thread calls and wait relationships.

A wakeup identifies a scheduling relationship: an execution context made the target runnable. It does not necessarily identify a lock owner, result producer or original root cause. Interrupt context, delegated wakeups, timeouts and missing events need separate investigation. After waking, the thread may still wait for CPU; separate sleeping time, wakeup-to-running delay and actual Running time.

For example, a synchronous Binder caller may wait for service execution, a lock or scheduling. This is a hypothesis to verify, not a general explanation for every slowdown after Monkey or with many background processes. Correlate the request/reply, peer thread and lock-owner evidence.

In the historical case below, the selection spans about 152.78 ms across Choreographer#doFrame / traversal, with substantial non-Running time visible in the state strip. That span merits investigation, but does not represent 152.78 ms of CPU execution or establish full input latency or a current device’s dropped-frame rate.

image-20211210185851589

Zooming in, the selected Runnable interval shows wakeup from tid: 20424. Running instead is a different scheduling observation, not the waker or lock owner. In Perfetto, correlate thread_state fields such as state, waker_utid, io_wait and blocked_function with CPU scheduling. These fields can be absent; an IRQ-context wakeup should not simply be blamed on the interrupted userspace thread.

image-20211213145728467

The original case identifies TID 20424 as RenderHeartbeat. The following crop shows that name but not its TID, so verify the mapping in the original trace, within the same process and time range, before inspecting app logic. One wakeup does not establish that RenderHeartbeat caused the entire long wait.

image-20211210190921614

A sleeping thread becomes runnable before being scheduled, but preemption can also move a Running thread back to Runnable without a new wakeup. Zooming can hide short intervals, and lost events can leave gaps. The separate historical example below records wakeup from tid: 31388; do not combine it with the 20424 example into one call chain.

The CPU slice’s stateWhenDescheduled describes the thread when it is switched out at the end of that run interval. S below means it went to sleep when switched out, not its state “before wakeup.” The original red annotation is incorrect on this point:

Separate Linux states from ps display modifiers. The following follows the procps-ng ps manual. Android ps implementations/options can differ; a complete STAT string is not a Perfetto state name.

Main state Meaning
R Executing or runnable, not only queued
S Interruptible sleep awaiting a condition/event
D Uninterruptible sleep, often I/O-related but not a disk diagnosis
I Idle kernel thread
T / t T: job-control stop; t: debugger tracing stop
Z / X Z: exited but not yet reaped; X: dead, normally not visible
W Obsolete paging state, unused since Linux 2.6

BSD-style STAT modifiers include < / N for higher/lower priority, L for locked memory pages, s for session leader (not defined by having children), l for multithreading, and + for a foreground process group. This + is unrelated to the preemption marker in a scheduling trace’s R+. See also the Linux v6.6 proc documentation.

Data Parsing in Information Panel

Thread State Interpretation

The selected Weibo main-thread Running interval starts at about 1358.039 ms, lasts 5.360 ms and runs on CPU 4. It describes this scheduling interval, not all of bindApplication. PID and thread name identify the subject. CPU 4 alone does not tell you whether it is a big or small core; check the device topology.

Function Slice Interpretation

The bindApplication slice has 593.686 ms Wall Duration and 116.462 ms Self Time. Wall duration includes execution and waiting. Self time subtracts nested child slices and may still include waiting; the image’s “excludes waiting” annotation is wrong. Self Time is not CPU Duration. Uninstrumented child calls are not automatically subtracted, and Category is an event classification rather than a complete call stack. See the calculation in Catapult SliceGroup.

Counter Sample Interpretation

This selects a sample from a counter series at a particular timestamp. Value 3 is the metric’s sampled value, not the number of counters. Counter/Series identify the metric and series. Check the source for units, cumulative versus instantaneous meaning and sampling interval; one sample is not automatically a total over an interval.

Async Slice Interpretation

The animator event’s 199.579 ms Wall Duration spans its asynchronous start and end. It is not 199.579 ms of continuous execution by one thread, nor GPU time. Follow the event’s association identifiers; summing overlapping or cross-thread asynchronous intervals does not give CPU consumption.

CPU Slice Interpretation

The selected CPU run for android.bg (TID 1416) lasts 37.654 ms and reports prio 130. This is a kernel scheduling-priority representation, not MHz or Java Thread’s 1–10 priority. stateWhenDescheduled: R+ means the task remained runnable when switched out, with a preemption marker; it is not a pre-wakeup state or foreground-process-group marker. Active slices link instrumentation and need not list every function.

User Expectation Interpretation

The legacy Interactions area shows viewer-derived intervals such as Rendering Response and Input Response. The selected Input Response spans 48.993 ms according to that analysis; it is neither a human tolerance threshold nor a direct touch-to-photon measurement. Check its event boundaries. Modern frame diagnosis can additionally use FrameTimeline on Android 12 / API 31+, but that does not automatically cover the complete input pipeline.

Using Shortcuts

Reading a trace means switching often between selecting, panning and zooming. A few shortcuts save a lot of clicking. These are the common legacy Systrace/Catapult shortcuts. Letter keys below mean lowercase without Shift. Do not assume every binding carries over to Perfetto:

Key Legacy UI action
w / s Zoom in / out
a / d Pan left / right
m Set the current selection as an interest range to compare boundaries
1 Selection: click events
2 Pan: drag to move
3 Zoom: drag to zoom
4 Timing: measure between selected endpoints

The default mouse mode may persist with viewer settings; press 1 explicitly for Selection. Keyboard focus also matters when editing a search field.

The Perfetto UI checked for this update is v58.3 (11fbaed83). Open Keyboard shortcuts under Support, or use ? to view its current help. Listed mouse controls include clicking events, dragging to select an area and Shift + drag to pan. On macOS the command palette uses Cmd + Shift + P; follow the modifier shown on other platforms. Legacy 1–4 mouse modes and m behavior are not a cross-version contract.

For current fields, see the PerfettoSQL Prelude: sched_slice describes CPU scheduling intervals, while thread_state describes thread states. utid is a trace-internal unique thread identifier, distinct from a reusable OS TID. Time fields are generally stored in nanoseconds and need conversion when read as milliseconds. Without the required scheduling/wakeup data, absent fields remain unknown, not zero waiting or proof that no waker existed.

Zhihu Article Link

Since blog comments are less convenient, feel free to visit the Zhihu or Juejin pages for this article to like or exchange ideas:
Zhihu - Android Systrace Basics - Prerequisites for Analyzing Systrace
Juejin - Android Systrace Basics - Prerequisites for Analyzing Systrace

About Me && Blog

Below is my personal intro and related links. I look forward to exchanging ideas with fellow professionals. “When three walk together, one can always be my teacher!”

  1. Blogger Intro: Includes personal WeChat and WeChat group links.
  2. Blog Content Navigation: A guide for my blog content.
  3. Curated Excellent Blog Articles - Android Performance Optimization Must-Knows: Welcome to recommend projects/articles.
  4. Android Performance Optimization Knowledge Planet: The paid community stopped operating in 2026 and no longer accepts new members; this link preserves its history.

One walks faster alone, but a group walks further together.

Scan WeChat QR Code

CATALOG
  1. 1. Table of Contents
  • Series Article Index
  • Main Content
    1. 1. Reading This Article with Perfetto
    2. 2. Viewing Thread States
      1. 2.1. Green: Running
      2. 2.2. Blue: Runnable
      3. 2.3. White: Sleep
      4. 2.4. Orange: Uninterruptible Sleep - IO Block
      5. 2.5. Purple: Uninterruptible Sleep
    3. 3. Analyzing Thread Wakeup Information
    4. 4. Data Parsing in Information Panel
      1. 4.1. Thread State Interpretation
      2. 4.2. Function Slice Interpretation
      3. 4.3. Counter Sample Interpretation
      4. 4.4. Async Slice Interpretation
      5. 4.5. CPU Slice Interpretation
      6. 4.6. User Expectation Interpretation
    5. 5. Using Shortcuts
  • Zhihu Article Link
  • About Me && Blog