Android Performance

Android Systrace Smoothness in Action 2 - Case Analysis - MIUI Launcher Scrol...

Word count: 2kReading time: 12 min
2021/04/24
loading

Different people have different understandings of smoothness (jank/dropped frames) and different perceptions of jitter thresholds. Therefore, before starting this series, it is necessary to clarify the content to avoid misunderstandings. Here are some basic explanations:

  1. For mobile users, jank encompasses many scenarios: dropped frames when scrolling lists, excessive white screen during app startup, slow screen wake-up when pressing the power button, unresponsive interface followed by a crash, no response when clicking an icon, incoherent window animations, lagging touch response, or stuttering when entering the desktop after a reboot. These scenarios differ slightly from what developers understand as “jank.” Developers categorize these more finely, which is a cognitive gap between developers and users that must be noted when handling feedback from users or testers.
  2. For developers, the above scenarios fall into three major categories: Smoothness (dropped frames in lists, incoherent animations, stuttering desktop entry), Responsiveness (long startup white screens, slow screen wake-up, lagging touch), and Stability (unresponsive interface/crashes, no response to icon clicks). This classification is used because each category requires different analysis methods and steps. Quickly identifying the category is crucial.
  3. Technically, Smoothness, Responsiveness, and Stability (ANR) all feel like “jank” to users because their underlying principles are identical: the main thread’s Message exceeds its processing deadline. They are simply categorized by different timeout thresholds. Understanding these problems requires knowledge of basic system operation mechanisms, which this article will introduce.
  4. This series primarily analyzes smoothness-related issues. Responsiveness and stability will be covered in dedicated articles. Understanding smoothness first will make analyzing responsiveness and stability much easier.
  5. This series focuses on using Systrace (Perfetto) for analysis. Systrace is our entry point because many factors affect smoothness—some within the app itself and others within the system. Systrace (Perfetto) provides a holistic view of the system’s operation during the problem, helping us initially pinpoint the root cause.

Table of Contents

Systrace Series Articles:

  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

If you are not familiar with the basic use of Systrace (Perfetto), please catch up on the Systrace Basics Series first. This article assumes you are already familiar with using Systrace (Perfetto).

The Routine for Analyzing Jank with Systrace

The general workflow for using Systrace to analyze jank is as follows:

  1. Reproduce the jank scenario and capture a Systrace using shell or built-in tools.

  2. Open the captured trace.html directly in Chrome.

    1. If it doesn’t open directly, type chrome://tracing/ in Chrome and drag the file onto the page.
    2. Alternatively, use Perfetto View and select “Open With Legacy UI.”
  3. Understand the context of the problem to improve analysis efficiency.

    1. User (or tester) operation steps.
    2. Reproduction probability.
    3. Whether competitor devices exhibit the same jank.
  4. Before or during analysis, check the Systrace for basic info:

    1. CPU frequency, architecture, Boost info, etc.
    2. Thermal throttling: Manifests as suppressed CPU frequencies.
    3. High load scenarios: Manifests as very dense tasks in CPU zones.
    4. Low memory scenarios: Manifests as busy lmkd, slow HeapTaskDeamon in the App process, or many Block IOs.
  5. Locate the App process in Systrace.

    1. The first thing to look at is the App process, specifically the UI thread and Render thread. Find time-consuming frames. E.g., the red box below shows a UI Thread taking 110ms—clearly abnormal (from a Bilibili list scroll jank case). image-20220228231805317

    2. In fact, any doFrame that exceeds a Vsync cycle (Yellow and Red frames) needs checking for actual jank. Even without jank, look for reasons. E.g.:

      image-20220228231830063

    3. Vsync cycle vs. Refresh rate:

      1. 60fps: 16.6ms cycle.
      2. 90fps: 11.1ms cycle.
      3. 120fps: 8.3ms cycle.
  6. Analyze the SurfaceFlinger process’s Main thread and Binder thread.

    1. Due to multiple buffer mechanisms, the App main/render threads might exceed a cycle without causing jank. Check SurfaceFlinger‘s Main thread to confirm. E.g., for the 110ms app frame above, the SF Main thread looks like this:

      image-20220228231855706

    2. The App’s Buffer count in the SF process area is also empty:

      image-20220228231914525

  7. System-wide and Binder call analysis (optional).

    1. In the Bilibili case, the bottleneck is clearly within the App itself. Optimizing the relevant View or logic would suffice.
    2. Sometimes the App UI thread is slow due to excessive Runnable states or Binder call timeouts, which requires system-wide analysis to find the root cause.

After following this routine, cross-reference data across processes to infer the most likely cause.

App frame drops have many causes. Refer to these articles; different causes have distinct Systrace signatures:

  1. Overview of Jank Causes in Android - Methodology
  2. Overview of Jank Causes in Android - System Side
  3. Overview of Jank Causes in Android - App Side
  4. Overview of Jank Causes in Android - Low Memory Side

Case Study: Analyzing Jank with Systrace

Systrace is the primary tool for analyzing jank, providing a global view to determine if jank is system-driven or app-specific.

However, for deeper analysis, Systrace can be limited. It often needs to be paired with TraceView and source code to pinpoint and solve issues, and then verified again with Systrace.

This article focuses on discovery and analysis. Solutions (like optimizing logic, scheduling, or layout) must be tailored to findings.

Case Description

On my Mi 10 Pro, I often felt a stutter during the common gesture of swiping the desktop. Since the Mi 10 Pro has a 90Hz screen and 90 FPS target, jank is very noticeable. After upgrading to MIUI 12.5, the issue remained, so I decided to investigate.

The captured Systrace revealed a perfect case study for smoothness analysis.

I recommend downloading the attached Systrace and following along with the article.

  1. Because many factors affect jank, I’ll clarify the hardware and software versions first. Findings apply to the attached Systrace even if the scenario is optimized later.
  2. Hardware: Mi 10 Pro
  3. Software: MIUI 12.5.3 Stable
  4. Launcher Version: RELEASE-4.21.11.2922-03151646

Starting with Input events

In the captured Systrace, I performed only one swipe, making it easy to locate. The input sequence consists of one Input Down, several Input Moves, and one Input Up.

In Systrace, we see InputDispatcher and InputReader threads in SystemServer, but we primarily focus on the App UI thread.

Input in Systrace

As shown above, deliverInputEvent on the App UI thread marks input processing. After “Input Up,” the “Fling” phase begins. Basics:

  1. Input Explained
  2. Weibo Image Loading Optimization Case

Analyzing the UI Thread

Since this jank mostly occurred after releasing the finger, we focus on the segment after “Input Up.”

UI Thread Post-Input-Up

UI thread frames are color-coded: Green, Yellow, Red. In this trace, there are no red frames, only green and yellow. Is a yellow frame always a jank? Not necessarily. We can’t confirm jank from the UI thread alone.

Identifying three suspicious points, we move to the RenderThread.

Analyzing the Render Thread

Zooming into the first suspicious point: total frame time is 19ms, with RenderThread taking 16ms. The RenderThread CPU state is “Running” (green). This delay is likely due to:

  1. RenderThread is busy with heavy tasks.
  2. RenderThread performance is bottlenecked by the CPU (low frequency or small cores).

RenderThread Suspicious Point

Before looking at the CPU, we check SurfaceFlinger to confirm actual jank.

Analyzing SurfaceFlinger

For basics on SF trace reading, see SurfaceFlinger Explained.

We focus on two points:

  1. Buffer status in the App’s BufferQueue. Does SurfaceFlinger have a buffer available from the app?
  2. SurfaceFlinger Main thread composition. If SF-vsync arrives and composition occurs, was it for our app?

Criteria for Judging Jank:

  1. If SF has no composition task and the App worked during that cycle but provided no Buffer to BufferQueue, jank occurred.
    (Matches the first suspicious point).

    SF Jank Type 1

  2. If SF performs composition but our App’s BufferQueue is empty, jank still occurred for our App. SF likely composited other layers.

    SF Jank Type 2

  3. If SF performs composition and our App has a Buffer available, everything is normal.
    (Provided for comparison).

    SF Normal

At the first suspicious point, SF confirms a frame was dropped because the App didn’t provide a Buffer. Why?

Back to the Render Thread

The 19ms total frame time (16ms in RenderThread) is unusual for a low-load scenario like desktop scrolling, especially since the previous frame was 3x faster. This isn’t a task load issue.

Check the RenderThread CPU info:

RenderThread CPU State

Since it’s “Running,” we check the Kernel area for scheduling details.

Analyzing CPU Info

See CPU Info Explained and Prerequisites for Systrace.

In this case, the RenderThread is mostly on CPUs 0 and 2—the Small Cores of the Snapdragon 865 (which has 4 Small, 3 Big, and 1 Prime core).

Small Core Scheduling

The frequency is capped at 1.8GHz (Small core max).

Small Core Frequency Trace

And there’s no CPU Boost active.

No CPU Boost

Hypothesis: Small cores even at max frequency can’t finish the task in time. Validation steps:

  1. Are normal frames also on small cores? (If yes without jank, the hypothesis is wrong).
  2. Are other janky frames also caused by small core scheduling?

Analysis reveals:

  1. Normal frames are NOT on small cores. After a jank, the scheduler immediately moves RenderThread back to big cores.
  2. Every janky frame was caused by RenderThread being scheduled on small cores which lacked the performance to finish on time.

Cause found: RenderThread being scheduled on Small Cores.

Scheduling is controlled by complexity algorithms based on task load. Optimizations:

  1. Adjust core migration thresholds or scheduler algorithms.
  2. Compare competitor strategies and scheduling indicators in similar scenarios.

What Role Does Triple Buffer Play in This Scenario?

In Triple Buffer Explained, we noted it helps:

  1. Mitigate jank.
  2. Reduce wait times.
  3. Lower bottlenecks.

However, in this Mi Launcher case, it sometimes had a negative impact, worsening the perceived jank:

See the Mitigating Jank principle:

Triple Buffer Principle

In the Mi Launcher trace, the BufferQueue sometimes dropped from 2 available buffers to 0, effectively discarding a buffer:

Discarding a Buffer

If a subsequent RenderThread timeout occurs during a Fling, no spare buffer is left to cushion it, resulting in an immediate jank. Triple buffering’s mitigation effect is lost.

Lost Cushioning

Furthermore, since Fling offsets are pre-calculated, discarding a frame buffer causes a visual “jump”:

Visual Jump

Example with scrolling offsets:

  1. Normal: 2→4→6→8→10→12
  2. Dropped (cushioned): 2→4→6→6→8→10→12 (Frame “8” delayed, user sees “6” twice—smooth decay).
  3. Discarded: 2→4→6→6→10→12 (Frame “8” discarded, jumps from “6” to “10”—feels like a jank + a jump).

Series Articles

  1. Systrace Smoothness in Action 1: Understanding Jank Principles
  2. Systrace Smoothness in Action 2: Case Analysis - MIUI Launcher Scroll Jank Analysis
  3. Systrace Smoothness in Action 3: FAQs During Jank Analysis

Attachments

Attachments are on GitHub: https://github.com/Gracker/SystraceForBlog/tree/master/Android_Systrace_Smooth_In_Action

  1. xiaomi_launcher.zip: Main analysis trace.
  2. xiaomi_launcher_scroll_all_the_time.zip: Continuous scrolling trace.
  3. oppo_launcher_scroll.zip: Comparison trace.

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: Welcome to join and thank you for your support~

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

Scan WeChat QR Code

CATALOG
  1. 1. Table of Contents
  • The Routine for Analyzing Jank with Systrace
  • Case Study: Analyzing Jank with Systrace
  • Case Description
    1. 1. Starting with Input events
    2. 2. Analyzing the UI Thread
    3. 3. Analyzing the Render Thread
    4. 4. Analyzing SurfaceFlinger
    5. 5. Back to the Render Thread
    6. 6. Analyzing CPU Info
  • What Role Does Triple Buffer Play in This Scenario?
  • Series Articles
  • Attachments
  • About Me && Blog