CN

loading
SmartPerfetto 1.19.0: A New Analysis Engine, and the Work Around It

SmartPerfetto 1.19.0 is out. Since the previous update, which covered 1.15.1, the largest change has been consolidating the analysis engine around Pi Agent Core. We also upgraded Perfetto, added analysis capabilities, and fixed problems uncovered by several rounds of TraceDemo testing.

Here is what matters in this update:

  • One default analysis engine: Pi Agent Core replaces the multiple-runtime default path. Web, CLI, and API share evidence acquisition and delivery. The old model declaration and claim-verification flow has been removed.
  • A more usable investigation process: add context while an analysis runs, keep source selections per conversation, and recover more reliably from long sessions, budget limits, interrupted connections, and unclear tool errors.
  • More evidence to work with: Perfetto v59.1, process lifecycle and JobScheduler observations, plus improvements to Bitmap, Doze, CPU PMU, camera, and rendering analysis.
  • Concrete results from multiple test rounds: synthetic cases, real traces, targeted reruns, and final release artifacts were checked separately. The details below preserve what each result can establish.
  • An independent option for your existing agent: install Perfetto-Skills in Codex, Claude Code, or OpenCode if you prefer working there rather than running the full SmartPerfetto product.

Download 1.19.0 · SmartPerfetto · Perfetto-Skills

SmartPerfetto 1.19.0 release cover

This is a standalone article following the previous update log. It covers 1.16.0 through 1.19.0. Pi became the default in 1.18.0; 1.19.0 continues the capability work and fixes that followed that migration.

AIW: An Android Systems and Performance Ebook You Can Check Against Source

AIW is an Android systems and performance ebook you can read online, download as an EPUB, and check against source code. Its five parts and 26 chapters connect application code with Framework, Native and Kernel mechanisms, including how to investigate them with Perfetto and other tools.

Bring a slow startup, janky scroll, ANR or battery problem to the book, or follow the contents to build a broader understanding. Both the web edition and the ebook are free to read:

This introduction reflects the content available in November 2026. The book remains in alpha. Android 17 / API 37 is the highest version covered by its definitive claims; the complete English edition is planned after v1.0. The book itself is currently in Chinese.

Android Perfetto Series 18: Response Latency in Practice, from Input Events to First-Frame Feedback

This article addresses a topic easily overshadowed by startup speed and smoothness: first-frame interaction response. It asks how long the screen takes to provide the first frame of feedback after a user action. Complete page loading and stability later in an animation require other metrics.

After tapping a button, how long until its pressed state appears? After tapping a WeChat conversation, how long until the first frame of the conversation page starts moving? After swiping a list, how long until its content follows the finger? These questions relate to slow startup and dropped frames, but need their own measurement definitions.

We use Perfetto to break down this interval: from InputReader read_time, through the App receiving the event, to an associated frame’s present. This gives a candidate internal delay, estimated_input_to_present_ms. Only after confirming the target layer and that the business state visibly changed on that frame should a report call it input_to_present_ms. Neither value covers touch IC latency, delays before driver reporting, display scanning, or panel response. By the end, you should be able to define a start, endpoint, capture configuration, SQL metrics, and supplementary App markers for a tap or scroll scenario.

The article examines response latency through four independent measurements—read/dispatch, handling, ACK→first frame, and scroll responsiveness. Each comes with capture configuration, the first tracks to inspect in the UI, and SQL. It then covers five common attribution paths and the respective boundaries of high-speed cameras and Perfetto.

Android Perfetto Series 17: Domain Automation, Issue Checklists, and Platform Infrastructure

For slow camera opens, audio underruns, a stalled WebView first screen, or dropped frames in Flutter and games, the evidence is scattered across the app, system_server, cameraserver/audioserver, HAL, SurfaceFlinger, and scheduling tracks. Simply inspecting a few more tracks in the UI can easily leave critical timestamps unnoticed.

Using Camera and Audio as examples, this article describes a reusable method for domain-specific analysis: capture the right data, identify the objects, calculate stages and blocking, and preserve timestamps in the report so that reviewers can return to the UI. Camera and Audio are examples; the core is a domain schema and collaboration with platform tracing. By the end, you should at least be able to break a slow camera open into reviewable stages and an audio underrun into cycle anomalies, rather than delivering only a table of the longest slices.

Android Perfetto Series 16: GPU, Power Counters, and Hardware Bottleneck Analysis

When FrameTimeline marks a late frame but the main thread and RenderThread show no obvious long tasks, GPU work and fences are useful next checks. GPU frequency, battery current, and power rails describe hardware state in that window; they do not establish on their own why an app frame presented late.

Parts 07 and 08 covered the rendering path from the App to SurfaceFlinger; Parts 06 and 09 covered refresh rates and CPU scheduling/frequency. This article adds an often-skipped step without repeating those topics: when a problem appears to have reached the hardware resource layer, how should GPU, devfreq, battery counters, and power rails enter the analysis of the same trace interval?

These counters are difficult because not every device provides them, and different GPU vendors use different counter names. A conclusion cannot simply say “a high GPU value means a GPU bottleneck.” FrameTimeline, RenderThread, SurfaceFlinger, the GPU timeline, frequency, and power data must be examined over the same interval.

Android Perfetto Series 15: Boot Traces, Long-Running Field Traces, and Capturing Intermittent Problems

Many performance problems cannot be reproduced with a single tap. Slow boot, intermittent jank, problems after turning the screen on or off, audio interruptions after several hours, periodic stutters in an automotive system, and performance degradation as temperature rises are all poor fits for a manually recorded 10-second trace.

This article covers long-running field traces: defining the observation window in advance, using triggers to preserve the incident, ensuring the file finishes writing safely, and determining whether the collected data is trustworthy. Boot tracing is covered below as a special observation window. Part 02 already covered basic interactive capture methods—the command line, official scripts, Developer options, and the web interface. Here, we focus on what changes in the field and during long-running recording.

Android Perfetto Series 14: heapprofd and Memory Profiling

The hardest part of a memory problem is that a rising number does not immediately tell you what is growing. dumpsys meminfo provides RSS/PSS, and a Java heap dump reveals object retention relationships. But for JNI/C++, CPU-side Skia/Bitmap allocations, and native wrappers in media players, you often also need to know which call stack issued the malloc/new request.

This article covers heapprofd. Its value is bringing native allocations, frees, and call stacks into a Perfetto trace, where you can inspect them alongside application events, thread scheduling, and Binder on the same timeline.

Use heapprofd after confirming the trend. I would split the growth between native heap, graphics buffers, and other mappings with meminfo or smaps before opening a flamegraph. Otherwise, it is easy to chase a malloc stack when the growth came from GraphicBuffer. This article does not address Java object references or graphics backing memory.

We will cover when to use heapprofd, how to capture a profile, how to read it in the UI and SQL, how to interpret sampling intervals and symbolization, and finally what to check before publishing a report.

Android Perfetto Series 13: Perfetto SDK, Track Event, and App Field Tracing

A system trace can tell you when a thread ran, which CPU core it ran on, and which FrameTimeline frame missed its deadline. With Binder/ftrace/sched evidence enabled, it can also reconstruct Binder calls and clues about waiting. But it does not know which frame ID a player is decoding, which scene a game engine is loading, or how long an application task has spent in a queue.

Track Events can record decoding, texture uploads, queue depth, and cross-thread task IDs. Put them in the same window as the system tracks to find a candidate application phase, then use RenderThread, GPU, and FrameTimeline evidence to check whether it affected a visible frame.

The article follows the practical integration order: decide whether instrumentation is needed and at which layer, define an application-phase dictionary and backend, then build the minimal integration, category controls, combined system capture, and cross-thread flows. Finally, control write volume and define the app-side field tracing protocol.

Android Perfetto Series 12: Trace Dataflow and Data Loss Troubleshooting

A trace can open in the UI and return SQL rows even after data was lost during capture. If thread-state intervals are missing, process names do not line up, or Track Events have IDs but no names, first find which stage lost the data, then decide which parts of the analysis can continue.

SQL can only analyze evidence that still exists in the trace. I would not discard an entire trace just because it reports ftrace loss; first identify whether scheduling, app markers, or frame data were affected.

Part 02 covered capture, and Part 11 covered SQL queries. This article focuses on one question: where did the trace lose data, which conclusions does that affect, and how should the next capture configuration change?

We will follow the data from the kernel to the trace file, locating loss at each stage: ftrace, producer shared memory, the central buffer, incremental state, and flush. Each stage loses data differently and needs a different remedy. At the end, there is a template for explaining how much of a trace remains trustworthy in an analysis report.

Android Perfetto Series 11: PerfettoSQL, Trace Processor, and Regression Detection

Selecting a window in Perfetto UI, inspecting the main thread, RenderThread, and CPU states, then taking screenshots works well for one investigation. When I open another trace or switch devices, I want to know whether I can calculate comparable, checkable numbers for the same kind of problem.

Part 11 covers PerfettoSQL and Trace Processor. The aim is straightforward: turn judgments made in the UI into queries that others can check, then use Python to run them across multiple traces. You do not need to become a SQL expert first. Treat a trace as a set of timestamped tables, and translate your visual assessment into a query you can run repeatedly.

The article follows one path: understand Trace Processor, express an assessment as a query over a defined time window, run it from the command line, process multiple traces with Python, and finally turn the results into stable metrics and Trace Summary output. Each step includes SQL you can reuse.

SmartPerfetto Is Open Source: A Perfetto AI Assistant for Android Trace Analysis

SmartPerfetto is now fully open source. Open the repository and you can see the runnable mainline project as it exists today: the Perfetto UI fork, the agentv3 backend, MCP tools, YAML Skills, scene strategies, scripts, and documentation. There is no private core module kept outside the repository, and this is not just a thin demo shell.

The project comes from a very concrete daily workflow: you have a trace in hand, Perfetto has already exposed the facts, but moving from facts to judgment still means jumping through tables, writing SQL, matching threads, checking FrameTimeline, finding the Binder peer, and then returning to the timeline to confirm everything again. SmartPerfetto tries to turn those repeated actions into tools, so performance engineers can spend more time on judgment.

It is still in development. I am releasing it now because trace analysis grows from real samples: real devices, real vendor differences, real product traces, and real PRs all change how Skills and strategies should be written. Waiting until every capability is stable before publishing it one way would miss the stage where samples matter most.

If you often open Perfetto to inspect scrolling jank, startup, ANR, Binder, CPU scheduling, or rendering pipelines, SmartPerfetto provides a Perfetto UI with an AI Assistant. After loading a trace, you ask questions in natural language. The backend queries trace_processor_shell, invokes YAML Skills, organizes evidence, and streams conclusions plus data tables back into the browser.

Project links:

For normal trial use, you only need the main repository. Gracker/perfetto is the frontend fork used by the perfetto/ submodule. It mainly matters to developers who want to modify the AI Assistant plugin UI.

The previous two technical articles are better for readers who want the engineering details:

Those two articles go deep into the internal architecture. Once the source is public, readers usually care more about what is actually in the repository, whether it can run, and which parts are not stable yet. This article focuses on the open-source release itself: what is open, what works today, how the internal pieces are divided, how to run it locally, and where collaboration is most useful.

Android Perfetto Series 8: Understanding Vsync Mechanism and Performance Analysis

Perfetto’s vsync-app, vsync-sf, and app doFrame tracks can look like the same event. This article follows a frame request from SurfaceFlinger scheduling to the app, then relates it to RenderThread, buffers, and FrameTimeline.

The examples mainly concern 120 Hz operation. Phase settings, hardware-callback enablement, and pending frame requests affect the tracks; separate those meanings before interpreting latency.

Version note (reviewed October 2026): Java, JNI, and scheduling code are checked against android-16.0.0_r1; app/appSf roles also reference Android 13 source. Historical screenshots are not universal Android 16/17 configurations. Excerpts omit surrounding state where noted and come from different classes, not one compilable program.

Android Perfetto Series 7: MainThread and RenderThread Deep Dive

During a scrolling slowdown, the main thread may be doing layout or may already have handed drawing work to RenderThread. This article follows their hand-off, buffer submission, and SurfaceFlinger activity in Perfetto screenshots to locate waits.

The focus is the hardware-accelerated View/HWUI path. Other engines and software drawing can use different threads. FrameTimeline and presentation-side evidence are needed to determine what reached the screen.

Android Perfetto Series 6: Why 120Hz? Advantages and Challenges

120 Hz reduces the nominal refresh interval from 60 Hz’s 16.67 ms to about 8.33 ms. Display refreshes, app-produced frames, and distinct frames presented are different counts. This article uses a historical Perfetto trace to explain their relationship and the rendering/power trade-offs.

Part five covered Choreographer callbacks; here the focus is the shorter display cycle. The screenshots describe that capture, not every 120 Hz device’s scheduling configuration.

Android Perfetto Series 4: Opening Large Traces via Command Line

This is the fourth article in the Perfetto series, explaining how to use trace_processor_shell to open large files exceeding 2GB locally. In actual problem analysis, we often encounter very large Trace files (greater than 2GB) that may fail to open in ui.perfetto.dev because of browser memory limits. The limit applies to memory used while parsing, not directly to the trace file’s size. In this case, we can use the official trace_processor_shell tool to open large files locally.

When I started this series, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were also migrating. Newcomers found the interface overwhelming and asked me to explain the subjects of my Systrace articles through Perfetto.

Android Perfetto Series 3: Familiarizing with the Perfetto View

The first two articles covered what Perfetto is and how to capture a trace. This third article starts after you open that trace: with so much on the screen, where do you look?

Android documentation labels Systrace a legacy tool and recommends Perfetto on Android 10+. When I wrote this article, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were migrating. This series continues the earlier analysis methods with Perfetto.

Technical review: 2026-10-14. The 2024 interface and case screenshots are retained. Updates to shortcuts and analysis semantics use official documentation and v58.3 source (11fbaed83636). The original case traces are not provided here; their illustrated wake-up chains and measurements are not new-version test results.

Android Perfetto Series 2: Capturing Perfetto Traces

The previous article Android Perfetto Series 1: Introduction to Perfetto introduced what Perfetto is. This article provides a brief introduction to Perfetto capture.

Android documentation labels Systrace a legacy tool and recommends Perfetto on Android 10+. When I wrote this article, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were also migrating. This series revisits the earlier analysis methods with Perfetto.

Technical review: 2026-10-14. The main examples target Android 12+. Original 2024 screenshots remain, with older-system and newer-UI differences explained below. Commands and configuration were checked against official documentation and script source; this update adds no new device-capture results.

Android Perfetto Series 1: Introduction to Perfetto

This is the first article in the Perfetto series. It mainly provides a brief introduction to the Perfetto tool, including its history, development, and what Perfetto can do.

Android documentation labels Systrace a legacy tool and recommends Perfetto on Android 10+. By the time I wrote this article, Perfetto had largely replaced Systrace in my daily work, and the OPPO and vivo teams I encountered were also migrating. Newcomers facing its complex interface asked me to revisit the Systrace articles using Perfetto.

Technical review: 2026-10-14. The original article and screenshots date from 2024. The updates below distinguish Android 10/11/12 data-source requirements and Perfetto v48.0/v49.0 UI changes from that earlier experience. Available data still depends on the device, recording configuration, and tool version.

Performance Considerations in Operating System Design

This article was originally written by Yingyun for my Knowledge Planet. Since the Planet has closed, I am publishing this series on OS performance design here.

Yingyun is a veteran performance optimization expert with deep insights into system-level tuning, having worked at several major smartphone manufacturers. He is currently active in our community. If you have any questions or feedback, feel free to join our WeChat group.

1. The Genesis

This starts a new series exploring the various considerations in OS architectural design. In reality, these principles apply to the design of any large-scale software.

My knowledge and experience have limits, and these views are subjective. There will be gaps. I would like to hear other views and see what I have missed.

Can an App Really Do Whatever It Wants With System Permissions?

In 2023, public research described vulnerability exploitation code and dynamically delivered DEX files associated with an Android app. I wanted to see which system capabilities this code attempted to use. I put the original article together in a hurry and did not examine all the code closely. The walkthrough remains here, with corrections based on the screenshots and AOSP source. The original references follow:

  1. Deep Blue Insight: The Most “Unpardonable” Vulnerabilities of 2022
  2. XXX apk embedded privilege escalation code and dynamic delivery dex analysis
  3. History of Android Deserialization Vulnerability Attack and Defense

Security is not my specialty. For background, see History of Android Deserialization Vulnerability Attack and Defense. This article does not reproduce the exploit chain or treat an API call as proof of root access.

The Performance Community Tea Talk - Episode 1

On Friday, March 25, 2022, at 9 PM, “The Performance” Knowledge Planet held its first online “Tea Talk.” We were joined by 3 planet hosts, 5 guest experts, and over 50 members. Thank you all for coming!

We had no set topic and expected to finish in an hour. We ended up talking for two and a half hours; introductions alone took an hour! We had talked plenty in the group and on Knowledge Planet, but this was our first voice chat together. People worked across the Android ecosystem, from app companies and phone manufacturers to chip companies and EV startups. Someone would mention their work, someone else would ask a question, and off we went.

At the time, we planned to hold more sessions with clearer themes and more guests, on topics beyond technology too. We did not record this session to protect participants’ privacy. The notes below reconstruct part of the conversation without including private details.

Systrace Thread CPU State Analysis Tips - Sleep and Uninterruptible Sleep

This is the third article in the “Systrace Thread CPU State Analysis Tips” series. It focuses on the Sleep and Uninterruptible Sleep states in Systrace—their causes, troubleshooting, and optimization. These states often represent normal waiting; investigate their conditions and dependencies when they delay a critical path.

The goal of this series is to use Systrace to view the Android system from a different perspective and to learn the Framework through visualization. While reading Framework source code can be difficult to remember, seeing the flow in Systrace can lead to deeper understanding. You can find the complete Systrace Basics and Action Series here.

Systrace Thread CPU State Analysis Tips - Running

This is the second article in the “Systrace Thread CPU State Analysis Tips” series. It analyzes the causes of the “Running” state in Systrace and provides optimization strategies for when Running segments are excessively long.

The goal of this series is to use Systrace to view the Android system from a different perspective and to learn the Framework through visualization. While reading Framework source code can be difficult to remember, seeing the flow in Systrace can lead to deeper understanding. You can find the complete Systrace Basics and Action Series here.

Systrace Thread CPU State Analysis Tips - Runnable

This is the first article in the “Systrace Thread CPU State Analysis Tips” series. It analyzes the causes of the “Runnable” state in Systrace and provides optimization strategies for when Runnable segments are excessively long.

The goal of this series is to use Systrace to view the Android system from a different perspective and to learn the Framework through visualization. While reading Framework source code can be difficult to remember, seeing the flow in Systrace can lead to deeper understanding. You can find the complete Systrace Basics and Action Series here.

Android Systrace Basics - SurfaceFlinger Explained

This is the fifth article in the Systrace series, primarily providing a brief introduction to the workflow of SurfaceFlinger. It covers several important threads within SurfaceFlinger, including Vsync signal interpretation, app buffer display, and jank detection. Since Vsync has already been covered in Systrace Basics - Vsync Explained and Detailed Explanation of Android Rendering Mechanism Based on Choreographer, it won’t be discussed in detail here.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - CPU Info Interpretation

This is the twelfth article in the Systrace series, primarily providing a brief introduction to the CPU information area (Kernel) in Systrace. It covers how to view CPU-related information output by the Kernel module, including CPU frequency, scheduling, frequency locking, and core locking.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Triple Buffer Explained

This is the eleventh article in the Systrace series, providing a brief introduction to Triple Buffer within Systrace. It covers how to identify jank in Systrace, perform preliminary localization and analysis, and explains the impact of Triple Buffer on performance.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Binder and Lock Contention Explained

This is the tenth article in the Systrace series, primarily providing a brief introduction to Binder and lock information in Systrace. It covers the basic situation of Binder, the representation of Binder communication in Systrace, how to view Binder information, and analysis of lock contention in SystemServer.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Vsync Explained

This is the seventh article in the Systrace series, primarily introducing the Vsync mechanism in Android. This article examines the display of each frame in the Android system from the perspective of Systrace. Vsync is a critical mechanism in Systrace. Although invisible and intangible when operating a phone, we can see in Systrace how the Android system, guided by Vsync signals, orderly performs rendering and composition for each frame, ensuring stable frame rates.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Comprehensive Record of Android App Startup Optimization

I’ve gathered the Android app startup optimization approaches I knew of when writing this article. Use them as a checklist: see what others have tried, then look for gaps in your own app. The details depend heavily on your business, so I won’t explain every implementation here. Once you find an approach that fits, follow up on that particular method.

I’ve also included some startup work done by system manufacturers, limited to the parts I know about. There are proprietary tricks I can’t cover here. Knowing what happens on the system side may still help, including when discussing whitelisting or SDK integration with a manufacturer.

Complete Guide to Android App Startup Optimization

I’ve gathered the Android app startup optimization approaches I knew of when writing this article. Use them as a checklist: see what others have tried, then look for gaps in your own app. The details depend heavily on your business, so I won’t explain every implementation here. Once you find an approach that fits, follow up on that particular method.

I’ve also included some startup work done by system manufacturers, limited to the parts I know about. There are proprietary tricks I can’t cover here. Knowing what happens on the system side may still help, including when discussing whitelisting or SDK integration with a manufacturer.

Android Systrace Basics - MainThread and RenderThread Explained

This is the ninth article in the Systrace series, primarily introducing the MainThread and RenderThread in Android Apps—commonly known as the Main Thread and Rendering Thread. This article examines their workflows from the perspective of Systrace and covers related topics: jank, software rendering, and dropped frame calculation.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Input Interpretation

This is the sixth article in the Systrace series, primarily providing a brief introduction to Input in Systrace. It covers the Input workflow, how Input information is represented in Systrace, and how to combine Input info to analyze related performance issues.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Overview of Jank and Frame Drops in Android - Application Layer

Technical review · 2026-10-13. The original 2019 images, thread listing, and author observations are retained. Technical checks use AOSP android-9.0.0_r1 and android-16.0.0_r1, with current entry points including API 31 frame timing and DataStore 1.2.1. The screenshots are not measurements of current app releases; no original-device or complete-trace reproduction was performed.

In the Overview of Jank and Frame Drops in Android - System Layer article, we listed causes of jank originating from the system. In this article, we focus on causes stemming from the App itself. When you encounter lag, before blaming the phone manufacturer, consider if it’s the App’s own inefficiency.

OEM and app teams may use Matrix or their own monitoring. System access can reveal more evidence, but coverage still depends on build, capture configuration, and platform support.

Average FPS alone does not describe smoothness. Two periods averaging 55 FPS can have different frame intervals and pauses. Consider intended cadence, actual presentation, and input response rather than using a change from 60 to 55 as a diagnosis. This four-part series includes:

Overview of Jank and Frame Drops in Android - System Layer

Technical review · 2026-10-13. These cases and screenshots date from 2019. The review uses relevant Android 8.1/9/16 source, Linux v6.6 documentation, and current Android documentation while preserving the images and the author’s experience. Long slices, CPU numbers, reclaim activity, and input pacing are no longer treated as standalone proof of root cause. No original-device rerun or complete trace replay was performed, and missing conditions are not invented.

The Application Layer article covers app-side problems. Here we organize cases around system services, display, scheduling, and memory. Hardware, kernels, and vendor implementations differ, so retain the actual system version and configuration.

OEM and app teams may use Matrix or their own monitoring. System privileges can expose more evidence, but capture scope still depends on build type, kernel configuration, and enabled sources.

Smoothness is not simply average FPS. An average of 55 FPS over one second on a 60 Hz display does not locate the delayed frames or determine every user’s perception. Examine intended pacing, actual presentation intervals, and input response. Static screens need not submit content on every refresh. The four-part series is:

Overview of Jank and Frame Drops in Android - Methodology

Technical review · 2026-10-13. This article retains the manufacturer’s optimization-team experience and industry opinions from 2019. The technical sections now distinguish Android 12 (API 31) FrameTimeline, JankStats, and Macrobenchmark. Looper logging was checked against AOSP android-9.0.0_r1 / android-16.0.0_r1; Matrix v2.1.0 is the documented feature baseline. No new device measurements were performed.

Jank issues in Android matter to both smartphone manufacturers and app developers. Internal performance or platform teams often investigate and optimize them.

Tools such as Tencent’s Matrix provide app-side performance evidence. Manufacturers can add their own instrumentation and use system source access and suitable debugging privileges to collect deeper data. Actual visibility still depends on the OS version, kernel configuration, build type, and enabled data sources.

Smoothness is not just average FPS. Two intervals averaging 55 FPS can contain very different frame spacing: one might include a noticeable pause, while another is more evenly paced. Consider the intended update cadence, actual presentation intervals, and input response together. Refresh intervals at 60/90/120 Hz are about 16.67/11.11/8.33 ms, but they are not fixed CPU budgets summed across every thread. A static screen need not submit new content on every refresh.

Causes can lie in the app, system, kernel, or display pipeline. This series has four parts:

A Detailed Guide to Activity Launch Modes in Android

Technical review · 2026-10-13. The 2019 sequences remain historical examples. Task selection, affinity, and Recents behavior were checked against AOSP android-9.0.0_r1 and android-16.0.0_r1; Android 12 (API 31) singleInstancePerTask is added below. The old records lack a complete device build identifier, and no device rerun was performed for this review.

Android Activities have several important launch modes: standard, singleTop, singleTask, and singleInstance. Plenty of articles explain these modes. I wrote a small demo to show how they change the arrangement of activities in tasks. The newer singleInstancePerTask mode is covered afterward.

Ordinary navigation within a task is commonly LIFO. Below, A -> B denotes the sequence of launch actions; task contents are listed top first. Keep an eye on the task contents after each action; following the changes makes the differences easier to see. Repeating a launch action does not necessarily create an instance. A Task is not a process or necessarily one visible Recents card.

I put the demo on GitHub too: AndroidLunchModeTest. The reviewed snapshot is eaa1f987e332e0f85187a911ad9ae01cd20fff05, using compile/target SDK 29 and min SDK 26. Its package is com.example.lunchmodetest, whereas the historical sequences below retain com.example.launchmodetest.

Check all navigation targets for each case. In the snapshot, MainActivity.startSingleTopActivity launches SingleTaskActivity, and StandardActivity launches SingleInstanceWithAffinityActivity by default. Changing one target does not implement every sequence. The WithAffinity classes actually use empty affinity; SingleTopWithAffinityActivity does not even declare singleTop. Class names are not configuration evidence. The sample code was inspected for this review; the project was not modified or compiled.

The explanations assume the same user, ordinary foreground Activity launches, and no extra Intent flags unless stated. Updating the old project to target SDK 31+ also requires explicit android:exported for components with intent filters; use true for the Launcher entry.

Android Systrace Basics - Prerequisites for Analyzing Systrace

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.

Android Systrace Basics - SystemServer Explained

Technical update — 2026-10-13: The historical screenshots and code are retained. Code excerpts were checked against AOSP android-10.0.0_r1; modern differences use android-16.0.0_r1 as an example. These tags do not identify the screenshot devices: the original traces, ROMs and build details were not supplied. The descriptions of animation ownership, StartingWindow and thread interactions are corrected below.

This is the fourth article in the Systrace series, primarily providing a brief introduction to SystemServer. It covers several important threads within SystemServer. Since Input and Binder are particularly critical, they are discussed separately and won’t be covered in detail here.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Introduction to Systrace

Technical update — 2026-10-13: First published in 2019, this article retains Systrace HTML and script workflows as historical references. Modern capture examples start from Android 11 / API 30+, with separate version requirements for app tracing APIs, permissions and data sources. Device-side atrace, host-side systrace.py and perfetto are different tools; their options are not interchangeable.

This is the first article in the Systrace series, primarily providing a brief introduction to Systrace, its basic usage, how to interpret Systrace traces, and how to analyze phenomena in Systrace in conjunction with other tools.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Systrace Basics - Why 60 FPS?

Technical update — 2026-10-13: First published in 2019, this article uses 60 Hz devices to explain frame pacing. 60 FPS is not a fixed standard for every Android device. The universal 16.67 ms budget, mismatched-rate examples and power claims are corrected below, with updated tools available from Android 11 / API 30 and Android 12 / API 31.

This is the third article in the Systrace series, explaining why 60 FPS is constantly emphasized. Here, FPS describes the app’s content frame rate, while Hz describes display refresh rate; they measure different things. For further context, refer to: A New Smooth Experience: A Talk on 90Hz.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

This article separates frame rate from refresh rate, then discusses pacing, power and response latency. On 90 Hz and 120 Hz devices, content updates still need to work with display timing, but 60 FPS and 16.67 ms are no longer universal targets.

Android Systrace -- Series Article Index

Technical update — 2026-10-13: This page is dated 2019 and retains update records from earlier tutorials. The old Systrace tooling workflow is obsolete. Read historical screenshots, source code and experiments against the Android versions stated in each article; they do not describe every current implementation. Start with the Perfetto series below for current capture and analysis workflows.

As Systrace and Android changed, my earlier tutorials started to show their age. I had also learned to read more from a trace, which helped me solve performance problems. I wanted to write those things down and get better at explaining what I had learned. If the notes helped someone else too, all the better.

The purpose of this series is to view the overall operation of the Android system from a different perspective using Systrace, while also providing an alternative angle for learning the Framework. Perhaps you’ve read many articles about the Framework but can never remember the code, or you’re unclear about the execution flow. Maybe from Systrace’s graphical perspective, you can gain a deeper understanding.

Android Code Memory Optimization Suggestions - OnTrimMemory

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

onTrimMemory(int level), introduced in Android 4.0 (API 14), hints when an app should reduce unnecessary memory usage. Trimming caches can help the system retain more background processes, but does not guarantee process survival or a faster next return.

This article keeps the Q&A format to explain callback delivery, integration, and cleanup. Decide what to retain by resource purpose, and make sure the UI can recover what was released.

Android Code Memory Optimization Suggestions - Android Resources

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

I wrote this because understanding common memory problems before writing the code can save a lot of diagnosis later. We will look at Bitmaps, database queries, list reuse, and drawing: who creates each resource, what keeps it alive, and when it is no longer needed. Retention, repeated allocation, and leaks need different remedies.

Android Code Memory Optimization Suggestions - Android (Official)

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

For GC to reclaim unused objects, longer-lived owners must stop retaining references that are no longer needed. Reachability from GC roots matters, not whether another object holds a reference: a group of mutually referencing objects can still be collected when the whole group is unreachable. Becoming unreachable does not mean GC runs immediately or that the memory is immediately returned to the OS.

Memory management also includes bounded caches, resource ownership, and component lifecycles. Close files, connections, and native resources through their own APIs rather than waiting only for their Java wrappers to be collected.

Android Code Memory Optimization Suggestions - Java (Official)

Android Memory Optimization Series:

  1. Android Code Memory Optimization Suggestions - Android (Official)
  2. Android Code Memory Optimization Suggestions - Java (Official)
  3. Android Code Memory Optimization Suggestions - Android Resources
  4. Android Code Memory Optimization Suggestions - OnTrimMemory

This article covers micro-optimizations in Android Java code. Choosing suitable algorithms and data structures still comes first; these techniques are most useful for reducing repeated work and temporary allocations in hot paths.

The original source was Google’s Android Training article, Performance Tips. “Java (Official)” in the title refers to its Java coding advice for Android, not to an Oracle Java performance specification.

Android Performance Patterns: Profile GPU Rendering

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): The three-color diagrams are retained from the 2015 video. Their Update / Execute / Process stages can be compared with Android 4.4.4 source. Android 6.0 and Android 16 use finer breakdowns and different reference-line implementations; the old legend does not apply unchanged to every device.

Original video introduction:

“If you can measure it, you can optimize it” is a common term in the computing world, and for Android’s rendering system, the same thing holds true. In order to optimize your pipeline to be more efficient for rendering, you need a tool to give you feedback on where the current perf problems lie.

In this video, Colt McAnlis walks you through an on-device tool built for this exact reason. “Profile GPU Rendering” will help you understand the stages of the rendering pipeline, see which portions might be taking too long, and decide what to do about it in your application.

Profile GPU Rendering Tool

Profile GPU Rendering is a quick on-device tool for finding operations associated with high rendering-stage costs. Despite its name, the bars do not directly measure GPU hardware execution time, and cannot identify every cause of jank on their own. See the official explanation.

Android Performance Patterns: Understanding VSYNC

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): The introduction and nine diagrams are retained from the 2015 video. The text corrects the fixed-60Hz assumption, tearing explanation, and “VSync copies the back buffer” description, and adds modern frame-rate hints and analysis tools.

Original video introduction:

Unbeknownst to most developers, there’s a simple hardware design that defines everything about how fast your application can draw things to the screen.

You may have heard the term VSYNC - VSYNC stands for vertical synchronization and it’s an event that happens every time your screen starts to refresh the content it wants to show you.

Effectively, VSYNC is the product of two components: Refresh Rate (how fast the hardware can refresh the screen), and Frames Per Second (how fast the GPU can draw images). In this video, Colt McAnlis walks through each of these topics and discusses where VSYNC (and the 16ms rendering barrier) comes from, and why it’s critical to understand if you want a silky smooth application.

Basic Concepts

To understand smoothness and jank, distinguish app frame production, system composition, and display presentation. VSync (vertical synchronization) coordinates their timing. It is not the mathematical product of refresh rate and FPS, nor an operation that renders the app’s content for it. See the AOSP VSync explanation.

Android Performance Patterns: Understanding Overdraw

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): The excerpts and diagrams are from the 2015 video. Overdraw remains a useful concept; the text now adds versioned color mappings, transparency exceptions, and conditions for removing backgrounds. Lighter overlay colors alone are not evidence of a performance gain.

Original video introduction:

One of the most problematic performance problems on Android is the easiest to create; thankfully, it’s also easy to fix.

OVERDRAW is a term used to describe how many times a pixel has been re-drawn in a single frame of rendering. It’s a troublesome issue, because in most cases, pixels that are overdrawn do not end up contributing to the final rendered image. As such, it amounts to wasted work for your GPU and CPU.

Fixing overdraw has everything to do with using the available on-device tools, like Show GPU Overdraw, and then adjusting your view hierarchy in order to reduce areas where it may be occurring.

What is Overdraw?

At the beginning of the video, the author uses a house painter as an analogy: painting a wall is hard work, and if you have to repaint it because you don’t like the color, the first layer was a waste of effort. Similarly, some drawing beneath a fully opaque region may make no contribution to the final image. When you try to balance high performance with perfect design, you often run into a common performance issue: Overdraw!

Overdraw means drawing the same pixel more than once within a frame. In the stacked-card example below, work beneath a fully opaque card may be unnecessary. Overlap is not always waste: translucent content, shadows, and antialiased edges still need the underlying color for blending. Removing that content would change the image. Clipping and renderer optimizations also affect the work performed. See the official explanation.

Android Performance Patterns: Render Performance

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

Technical review (2026-10-13): This is a study note from the 2015 video series. The Nexus 5 example and tool screenshots remain historical material. The original introduction uses 16ms as an approximation for 60Hz; the discussion below now clarifies refresh behavior, jank, and tool limitations.

Original video introduction:

Rendering performance is all about how fast you can draw your activity, and get it updated on the screen. Success here means your users feeling like your application is smooth and responsive, which means that you’ve got to get all your logic completed, and all your rendering done in 16ms or less, each and every frame. But that might be a bit more difficult than you think.

In this video, Colt McAnlis takes a look at what “rendering performance” means to developers, alongside some of the most common pitfalls that are ran into; and let’s not forget the important stuff: the tools that help you track down, and fix these issues before they become large problems.

Android Rendering Knowledge

When you think you’ve developed a world-changing app, your users might not agree. They might think your app is slow and laggy, failing to achieve the smoothness they expect, let alone changing the world. Straight into the bin! Hang on, it runs smoothly on my Nexus 5. How can it be slow? If you know anything about Android fragmentation, you’d know that many low-end phones don’t have the powerful processor and GPU of a Nexus 5, or the same clean stock Android installation.

If a large number of users complain that your app is laggy, don’t just blame their hardware. Sometimes the problem lies within the app itself, including rendering work or a blocked main thread. Measure first to identify the cause and choose a fix. Thus, knowing how Android rendering works is essential for any Android developer.

Overview of Android Performance Patterns

Series Catalog:

  1. Overview of Android Performance Patterns
  2. Android Performance Patterns: Render Performance
  3. Android Performance Patterns: Understanding Overdraw
  4. Android Performance Patterns: Understanding VSYNC
  5. Android Performance Patterns: Profile GPU Rendering

In 2015, Google introduced the Android Performance Patterns short-video series. The original playlist is on YouTube; Google’s companion-course announcement also documents the series.

Android Performance Patterns Overview

Technical review — 2026-10-13: The original 2015 motivation and viewing experience are retained. The videos remain useful background, while the old tools, Google+ resources, and fixed “16ms” guidance need the version context below.

Overdraw, VSYNC, and main-thread/RenderThread cooperation still matter, but the refresh interval is not always 16ms. It is about 16.67ms at 60Hz, 11.11ms at 90Hz, and 8.33ms at 120Hz. Use the system’s scheduling deadlines and trace data when judging actual frames instead of applying one fixed threshold to every device and scenario.

Investigation Current entry point and conditions
View / Compose hierarchy and attributes Use Layout Inspector on debuggable apps. It can also show Compose recomposition/skipping; hierarchy inspection is not a frame-duration measurement
Quick rendering-stage and overdraw signals Developer options provide Profile GPU/HWUI Rendering and Debug GPU Overdraw. The bars represent CPU-side rendering stages, not pure GPU execution time, and do not cover every custom rendering path. See the official guide
Frames missing their deadlines Perfetto FrameTimeline requires Android 12 / API 31+. Relate frames to the thread, scheduling, and SurfaceFlinger tracks actually captured
Regressions during scrolling or transitions Macrobenchmark FrameTimingMetric is available from AndroidX Benchmark 1.1.0. frameOverrunMs requires API 31+ and measures something different from frameDurationCpuMs

The old Android Device Monitor, which hosted Hierarchy Viewer and Traceview, was deprecated in Android Studio 3.1 and removed in 3.2. Use the current Profiler for method analysis and Layout Inspector for hierarchy inspection. For Macrobenchmark, follow the setup requirements: a release-like, non-debuggable, profileable target, with consistent device and scenario conditions.

Introduction quoted in the original 2015 article:

Android Performance Patterns is a collection of videos focused entirely on helping developers write faster, more performant Android Applications. On one side, it’s about peeling back the layers of the Android System, and exposing how things are working under the hood. On the other side, it’s about teaching you how the tools work, and what to look for in order to extract the right perf out of your app.

But at the end of the day, Android Performance Patterns is all about giving you the right resources at the right time to help make the fastest, smoothest, most awesome experience for your users. And that’s the whole point, right?

The videos explain Android performance in three to five minutes each. The speakers talk fast; before subtitles were available, they really tested my listening. Subtitles were available when this article was written; check each video’s current subtitle tracks rather than assuming complete coverage today.

While the videos are short, they are packed with information. A point the speaker passes over in one sentence can take a lot of reading to understand, or a while spent learning a debugging tool. This means the series doesn’t directly teach you “how to optimize your app” step-by-step; rather, it tells you what you need to know about Android performance so that you know which tools to use, what steps to take, and what goals to aim for.

Android Memory Optimization (3) - Viewing Original Bitmaps in MAT

This is the final article in our MAT series, detailing how to reconstruct original images from memory snapshots to debug leaks.

  1. Android Memory Optimization (1) - Introduction to MAT
  2. Android Memory Optimization (2) - Advanced MAT Usage
  3. Android Memory Optimization (3) - Viewing Original Bitmaps in MAT

Technical review — 2026-10-13: This historical technique depends on the Bitmap implementation. The original screenshots are retained. The field is checked against AOSP android-4.4.4_r2; Android 8.0 / API 26 explains the native-pixel change. Updated GIMP 3.2.6 import settings and a current debugging alternative follow.

When investigating image-related memory problems in MAT, knowing which image a Bitmap contains makes the object much easier to connect to an app feature. “Original image” here means the pixels held by the runtime Bitmap, not the downloaded JPEG/PNG, its compression settings, or EXIF. MAT can show what retains the object; a large Bitmap alone does not establish a leak.

This workflow requires the dump to contain the pixel array. A Java wrapper and a native address alone cannot reconstruct pixels missing from the dump.

Android Memory Optimization (2) - Advanced MAT Usage

This is the second article in our MAT series, focusing on advanced techniques for analyzing memory issues in Java and Android applications.

  1. Android Memory Optimization (1) - Introduction to MAT
  2. Android Memory Optimization (2) - Advanced MAT Usage
  3. Android Memory Optimization (3) - Viewing Original Bitmaps in MAT

Technical review — 2026-10-13: The 2015 screenshots are retained; concepts and query descriptions were checked against MAT 1.17.0 documentation. The old Studio conversion/GC menus are historical. Reference directions, unreachable-object interpretation, and leak criteria are corrected below, with missing steps restored.

For capture, see the introductory article: obtain a heap dump in Android Studio Profiler with debuggable / complete data, then export to MAT as needed. LeakCanary can support automated tests, but the ordinary leakcanary-android dependency belongs in debug builds. The official 2.14 release-analysis workflow is still marked experimental; adding LeakCanary is not a generic production-capture strategy. See UI-test integration and LeakCanary for releases.

Characteristics of Java Memory Leaks

  • A typical Java memory leak is an object that is still reachable but no longer useful.
  • Compare its intended lifetime with the actual ownership path, rather than judging only its size or instance count.
  • Recreating reusable objects adds allocation and GC work. If old objects are collected normally, that is allocation waste, not necessarily a leak. An oversized legitimate allocation can also cause OOM.

Advanced MAT Techniques

Dumping Memory with Android Studio

The screenshot shows an early Android Studio capture UI:

Historical Android Studio heap tools

Android Memory Optimization (1) - Getting Started with MAT

This is the first article in the series on using the MAT tool. This series consists of three articles, detailing how to use MAT to analyze memory issues, whether they are Java application memory issues or Android application memory issues:

  1. Android Memory Optimization (1) - Getting Started with MAT
  2. Android Memory Optimization (2) - Advanced MAT Usage
  3. Android Memory Optimization (3) - Opening Original Bitmap Images in MAT

Technical review — 2026-10-13: The tutorial and historical screenshots are retained. MAT’s heap-analysis concepts remain useful, while the Eclipse/DDMS capture workflow is obsolete. Installation requirements now reference MAT 1.17.0 (2026-06-10; Java 21+ for the standalone tool). The ART, Bitmap, retained-size, and reference explanations have been corrected.

Start with a Java/Kotlin heap dump in Android Studio Profiler, then export to MAT when its analysis is useful. LeakCanary can help find Android memory leaks. MAT mainly explains why managed-heap objects remain reachable; process-wide memory and native allocations also require tools such as dumpsys meminfo, native allocation recording, or Perfetto heapprofd on Android 10+. On user builds, heapprofd requires a debuggable or profileable app; it cannot arbitrarily profile other apps.

Introduction to MAT

What is MAT?

MAT (Memory Analyzer Tool) is an Eclipse-based Java heap analyzer. It helps us find memory leaks and reduce memory use by showing how much space objects occupy and which references keep them alive. Its reports give us places to start investigating.

image

MAT is available as an Eclipse plugin or a standalone Eclipse RCP application. The standalone tool does not require a full Eclipse IDE, but it still needs a compatible Java runtime. Whether an Android HPROF needs conversion depends on its format and the analyzer’s support, not on which MAT installation method you chose.

Android Performance Case Study Follow-up

Introduction

This is an annotated edition of Android Performance Case Study Follow-up by Romain Guy. The first-person case narrative below belongs to the original author.

Technical review — 2026-10-13: The 2015 Falcon Pro 3 / Moto X 2014 case is retained. Android Device Monitor, which hosted Tracer for OpenGL ES and Hierarchy Viewer, was deprecated in Android Studio 3.1 and removed in 3.2. The old workflow is historical; an Android 12+ Perfetto workflow is added below. The original website could not be reopened during this review; the technical corrections use the linked official documentation and versioned source.


Case study

Two years ago, I published Android Performance Case Study to help Android developers understand the tools and techniques needed to identify, track, and optimize performance bottlenecks.

That article used the Twitter client Falcon Pro as a case study. Its developer, Joaquim Vergès, was kind enough to let me use his app as an example and quickly addressed the issues I found. Fast forward to recently: Joaquim was building Falcon Pro 3 from scratch. Before its release, he contacted me about a scrolling performance issue. Once again, I had to analyze it without access to the source code.

Android Performance Optimization: Overdraw - Practical Application

Introduction

The previous article covered the theory of overdraw and tools to detect it. While iOS users rely on Apple’s curation, Android users rely on developers’ discipline. Unfortunately, many market-leading Android apps still suffer from significant overdraw issues. As a developer, I want to see Android bridge and eventually surpass the experience gap with iOS.

This post follows one overdraw optimization case. It uses only a few of the available techniques; apps differ, and so will the changes they need. Treat it as an example. Getting this right still takes work.

If you missed the theory part, check it here: Android Performance Optimization: Overdraw (Part 1)


Android Performance Optimization: Overdraw - Theory

Updated 2026-10-13: This article was written in 2014. Its source excerpts have been checked against AOSP android-4.4.4_r2. Overdraw remains relevant, but ADT, monitor, Hierarchy Viewer, and the old OpenGL tracing workflow are outdated. Android Studio 3.1 and later use Layout Inspector for hierarchy inspection; use Perfetto for frame timing. The historical source is retained below, with Android 12 and Android 16 boundaries added.

It’s been a while since my last update. After joining a new company, things have been busy, but I’ve been spending a lot of time researching Android performance. I’ve realized there’s so much I still don’t know, so I’m starting from the application level and working my way down. This series will document my learnings on Android performance optimization.

First, we’ll discuss GPU Overdraw, which is often the most direct point of contact for developers. This topic is split into two parts: Part 1 covers the theory and optimization suggestions, and Part 2 will walk through a practical optimization example.

What is Overdraw?

GPU overdraw means drawing the same pixel more than once within a frame. For example, drawing a TextView background and then its text can draw the pixels under the characters twice. Extra shading, blending, and memory accesses cost resources, but whether they cause missed frames depends on area, transparency, GPU capabilities, and the rest of the frame’s work. A color overlay alone cannot establish the performance impact. See Android’s overdraw guide.