Series Catalog:
- Overview of Android Performance Patterns
- Android Performance Patterns: Render Performance
- Android Performance Patterns: Understanding Overdraw
- Android Performance Patterns: Understanding VSYNC
- 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.
Use the bars to identify a suspicious operation, then examine its thread, scheduling, GPU, and composition evidence in a system trace. An app’s HWUI bars are not a complete SurfaceFlinger timeline and do not cover every custom OpenGL/Vulkan rendering path.
On Android 4.1 / API 16+, look for Profile GPU Rendering or Profile HWUI Rendering in Developer options and select On screen as bars. Names and locations vary by version and vendor:

The historical example shows blue, red, and orange/yellow segments with a green reference line:

This screenshot contains graphs for the app and System UI windows: one near the status bar, one near navigation, and one for the app. Their positions are not a universal rule that the top measures notifications and the bottom navigation. Identify the window each graph belongs to.
Using the GPU Profile Tool
Each bar represents a recorded frame for that window, with segment heights showing the measured stage durations. Only a limited history remains visible. These bars are neither FPS values nor full input-to-display latency measurements. A static page may produce no new drawing work, so the absence of new bars does not itself mean a freeze.
The Green Line
The historical figure labels the line 16ms. This matches getThreshold() returning 16 in Android 4.4.4 HardwareRenderer. Android 6.0 FrameInfoVisualizer also uses a fixed 16ms reference, whereas a 60Hz period is approximately 16.67ms.
Crossing the line warrants investigation, but does not prove the user saw a stutter; staying below it does not guarantee timely presentation. At 90Hz and 120Hz, periods are about 11.11ms and 8.33ms. Use the device’s actual reference-line implementation and frame deadlines for newer or high-refresh systems.

The Bar Colors
First, consider the old three-segment graph. The timing scopes below are checked against Android 4.4.4 Java HardwareRenderer; the exact system build used by the video is not established:

Blue: Update / Draw
The old implementation times display-list construction or updates inside buildDisplayList(). This includes drawing logic for Views that need updating; it does not rerun every View’s onDraw each frame, or measure the entire measure/layout pass. Unchanged display lists can be reused.

A tall blue segment is a reason to investigate frequent invalidation, expensive drawing code, or work that could leave the drawing path. Use a trace to locate the cost.

Red: Execute / Issue commands
The old timer wraps canvas.drawDisplayList(), including CPU-side replay and command submission. OpenGL ES in the illustration describes that version’s rendering path. Submitted commands do not mean the GPU has finished or the image is on screen.

Many drawing operations, complex paths, or waits during submission can increase this segment. A complex custom View is a candidate cause, not a conclusion established by red bars alone.


Transforms or animations can resubmit cached display lists without recording them again. Red can therefore increase without blue increasing, and this does not prove that every underlying View reran onDraw(). See the stage analysis.
Orange/yellow: Process / Swap buffers
Android 4.4.4 measures around eglSwapBuffers(). The old illustration says glSwapBuffers; the relevant API is EGL’s eglSwapBuffers. This is not simply the CPU waiting for the GPU to acknowledge a command. CPU and GPU work can run asynchronously; driver or buffer-queue backpressure, including waiting for a reusable buffer, can lengthen the call. A tall segment points to a wait/submission path, not proof of insufficient GPU compute power or a direct GPU execution-time measurement.
Reading Android 6.0 / Android 16 graphs
Android 6.0 / API 23 FrameInfoVisualizer and the Android 16 / API 36 implementation use seven segments. This table summarizes those source tags; vendor colors are not a fixed API contract.
| Color | Stage | What the interval helps investigate |
|---|---|---|
| Teal | Misc / VSync delay | IntendedVsync to HandleInputStart; may include a late start or other main-thread work |
| Dark green | Input / Animation | Input handling and animation-related work |
| Light green | Measure / Layout | Traversal start to DrawStart; measurement and layout |
| Blue | Draw | DrawStart to SyncStart; drawing-command recording and related work |
| Light blue | Sync / Upload | Rendering synchronization and resource preparation |
| Red | Issue commands | IssueDrawCommandsStart to SwapBuffers |
| Orange | Swap buffers | SwapBuffers to FrameCompleted |
The Android 16 source also draws green, lime, and red reference lines at 0.8, 1.0, and 1.5 times the supplied frameInterval, scaling the vertical axis. A green horizontal line no longer universally means 16ms. These are timing intervals, not guarantees that each contains only one kind of work; a color cannot represent all costs of one component in a mixed View/Compose page.
Record the system version, refresh rate, action, and most prominent stage. On Android 12 / API 31+, use Perfetto FrameTimeline to compare expected and actual frames; use available system-trace evidence on older systems. After a fix, disable on-screen debug overlays and run the same scenario/device with Macrobenchmark. FrameTimingMetric was added in AndroidX Benchmark 1.1.0; frameOverrunMs requires API 31+ and differs from frameDurationCpuMs. Follow the configuration requirements for a non-debuggable, profileable target app.
Summary
The GPU Profile tool is great for finding rendering issues, but fixing them requires deeper code analysis to find and optimize specific bottlenecks. Sometimes, you can use these metrics to convince designers to adjust their requirements for a better user experience.
Perf Matters
Keep calm, profile your code, and always remember, Perf Matters.
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!”
- Blogger Intro
- Blog Content Navigation: A guide for my blog content.
- Curated Excellent Blog Articles - Android Performance Optimization Must-Knows
- 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.
