Understanding VSync and Measuring Smoothness on Android
This article explains Android's VSync mechanism, defines smoothness metrics such as FPS, skipped frames and smoothness, describes how VSync timing affects rendering, and provides practical testing commands like `adb shell dumpsys gfxinfo` and `adb shell dumpsys SurfaceFlinger` for measuring frame performance.
Google defines smoothness as running at a consistent 60 frames per second without any dropped or delayed frames, often referred to as "jank". In other words, the app should render at 60 fps (each frame ~16.6 ms) with no delays.
To evaluate smoothness we consider three indicators:
FPS – frames per second.
Skipped Frame (SF) – when work that should finish within 16.6 ms overruns and occupies subsequent intervals, effectively losing frames.
Smoothness (SM) – the number of loop iterations within a second under VSync, complementary to skipped frames.
VSync is a vertical synchronization mechanism that Android triggers every ~16 ms. It sends a VSync signal that initiates UI rendering. VSync, originally used on PCs, became part of Android starting with version 4.1 (Jelly Bean).
The diagram below shows the rendering pipeline under VSync. When both CPU and GPU finish their work in less than one VSync interval (16.6 ms), the resulting FPS is 60.
If processing takes longer than the VSync interval, frames are delayed or dropped, leading to jank. The second diagram illustrates this situation where CPU/GPU work exceeds 16.6 ms, causing skipped frames and a perceptible stutter.
Testing smoothness can be done with the gfxinfo command via dumpsys . The command:
adb shell dumpsys gfxinfo <PACKAGE_NAME>produces detailed frame statistics, for example:
Stats since: 752958278148ns
Total frames rendered: 82189
Janky frames: 35335 (42.99%)
90th percentile: 34ms
95th percentile: 42ms
99th percentile: 69ms
Number Missed Vsync: 4706
Number High input latency: 142
Number Slow UI thread: 17270
Number Slow bitmap uploads: 1542
Number Slow draw: 23342The fields mean:
Total frames rendered – total number of frames captured.
Janky frames – frames that were dropped or delayed.
Number Missed Vsync – frames that missed the VSync signal.
Number High input latency – frames where input processing exceeded the deadline.
Number Slow UI thread – frames delayed due to heavy work on the UI thread.
Number Slow bitmap uploads – frames delayed by bitmap loading.
Number Slow issue draw commands – frames delayed by drawing commands.
Another useful tool is SurfaceFlinger , the Android service that composes surfaces. Its latency command:
adb shell dumpsys SurfaceFlinger --latency <window_activity>returns the most recent 128 frames for the specified window. The first line is the refresh period (nanoseconds). The following 127 lines contain three columns: the time when the app started drawing, the VSync timestamp preceding the submission, and the timestamp after the frame was submitted to hardware. FPS can be calculated as total frames divided by total refresh time.
Why might a low FPS not feel janky? If an animation finishes quickly (e.g., 0.5 s) the maximum FPS is limited by its duration, and a static screen may report 0 FPS without any perceived lag. Therefore, FPS alone is not a sufficient metric; test scenarios must reflect realistic user interactions.
Reference: Android Performance Testing Guide
Qtest, the professional testing team of 360, promotes testing technology platformization and efficiency for the Web platform department.
360 Quality & Efficiency
360 Quality & Efficiency focuses on seamlessly integrating quality and efficiency in R&D, sharing 360’s internal best practices with industry peers to foster collaboration among Chinese enterprises and drive greater efficiency value.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.