Android 通过从您的应用生成帧并在屏幕上显示来呈现 UI。如果您的应用 UI 渲染缓慢,则系统将被迫跳过帧。发生这种情况时,用户会在屏幕上看到反复闪烁,这被称为卡顿。
发生卡顿时,通常是由于 UI 线程(在大多数应用中是主线程)上的一些减速或阻塞异步调用造成的。您可以使用系统跟踪来识别问题所在。
在 Android 12 及更高版本上检测卡顿
对于使用 Android 12(API 级别 31)或更高版本的设备,捕获的跟踪显示在 CPU 分析器的 **显示** 面板下的 **卡顿帧** 轨迹中。
要检测卡顿,
在 Android Studio 中,选择 **查看 > 工具窗口 > 分析器** 或点击工具栏中的 **分析** 。
如果选择部署目标对话框提示您,请选择要部署应用进行性能分析的设备。如果您已通过 USB 连接设备但未看到它列出,请确保已启用 USB 调试。
单击CPU时间轴中的任意位置以打开 CPU Profiler。
在 CPU Profiler 的配置菜单中选择系统跟踪,然后单击记录。完成与应用的交互后,单击停止。
您应该在显示下看到卡顿帧轨迹。默认情况下,Profiler 只显示卡顿帧作为调查对象。在每个卡顿帧中,红色部分突出显示帧超过渲染截止时间持续的时间。
找到卡顿帧后,单击它;或者,您可以按M键调整缩放比例以聚焦于选定的帧。相关事件在这些线程中突出显示:主线程、RenderThread和GPU 完成。
您可以选择查看所有帧或渲染时间的细分,方法是分别切换所有帧和生命周期复选框。
在 Android 11 上检测卡顿
对于使用 Android 11(API 级别 30)的设备,捕获的跟踪显示在 CPU Profiler 的帧生命周期部分。
帧生命周期部分包含图层名称和四个轨迹。每个轨迹代表帧渲染管道中的一个阶段。帧生命周期元素如下所示:
- 帧生命周期(图层名称):此部分标题包含括号中的图层名称。图层是单个合成单元。
- 应用程序:此轨迹显示从应用出队缓冲区到将其排队返回的时间。这通常对应于
RenderThread
中的跟踪事件。 - 等待 GPU:此轨迹显示缓冲区由 GPU 拥有的时间长度。这是从缓冲区发送到 GPU 到 GPU 完成其在缓冲区上的工作的时间。这并不表示 GPU 在此期间仅处理此缓冲区。有关 GPU 在给定时间处理内容的详细信息,您可能需要使用Android GPU Inspector。
- 合成:此轨迹显示从 SurfaceFlinger 锁定缓冲区并将其发送进行合成开始的时间,到缓冲区发送到显示器的时间。
- 显示上的帧:此轨迹显示帧在屏幕上的时间长度。
帧生命周期部分说明了帧缓冲区如何在渲染管道的不同阶段之间移动。帧按帧编号进行颜色编码,以便更容易跟踪特定帧。
Android Studio 还以表格格式在所有帧选项卡中显示跟踪中的所有帧。
帧 #、应用程序、等待 GPU和合成列代表与上述帧生命周期部分中的轨迹相同的数据。帧持续时间列表示从应用程序开始到显示上的帧开始的时间。这实际上是端到端渲染帧所需的时间。
您可以按任何列对帧表进行排序,以快速查找最短或最长的帧。该表还支持分页控件,可帮助您浏览数百个帧。
要在 Android 11 上检测和调查卡顿,请按照以下步骤操作:
按降序对所有帧表中的应用程序列进行排序,以便最长的帧首先显示。
找到运行时间最长的帧并选择表格行。这会在左侧的时间轴视图中放大选定的帧。
查看帧生命周期和线程部分中的相关线程。
在 Android 10 及更低版本上检测卡顿
对于使用 Android 10(API 级别 29)及更低版本的设备,相关的操作系统图形管道信息显示在 CPU Profiler 系统跟踪上的单个部分中,称为显示。
- 帧:此部分显示应用中的 UI 线程和
RenderThread
跟踪事件。长于 16 毫秒的事件将以红色显示,以突出显示潜在的卡顿帧,因为它们超过了以每秒 60 帧 (fps) 渲染的截止时间。 - SurfaceFlinger:此部分显示 SurfaceFlinger 何时处理帧缓冲区。SurfaceFlinger 是负责将缓冲区发送到显示器的系统进程。
- VSYNC:此部分显示 VSYNC,这是一种同步显示管道的信号。该轨迹显示 VSYNC-应用信号,该信号显示您的应用何时启动得太晚。通常,这是因为 UI 线程繁忙。这会导致动画过程中屏幕上出现明显的闪烁,并在动画或滚动完成之前增加额外的输入延迟。对于高刷新率显示器,这尤其重要,因为它们可能比每秒 60 次更频繁地出现或以可变速率出现。
- BufferQueue:此部分显示有多少帧缓冲区已排队并正在等待 SurfaceFlinger 使用。对于部署到运行 Android 9(API 级别 28)或更高版本的设备的应用,此轨迹显示应用界面的缓冲区计数BufferQueue(
0
、1
或2
)。BufferQueue 可以帮助您了解图像缓冲区在 Android 图形组件之间移动时的状态。例如,值2
表示应用当前正在进行三缓冲,这会导致额外的输入延迟。
显示部分提供了检测潜在卡顿的有用信号,例如,当 UI 线程或RenderThread
花费的时间超过 16 毫秒时。要调查导致卡顿的确切细节,您可以探测线程部分,该部分显示与 UI 渲染相关的线程。
在上图中,线程部分显示 UI 线程(java.com.google.samples.apps.iosched
)、RenderThread
和GPU 完成
线程。这些是与 UI 渲染相关的线程,可能会导致卡顿。
要在 Android 10 或更低版本上检测卡顿,请按照以下步骤操作:
查看显示中的帧轨迹。红色帧是需要调查的对象。
找到潜在的卡顿帧后,通过按
W
键或按住Control键(macOS 上为Command键)的同时滚动鼠标滚轮来放大。继续放大,直到您开始在 UI 线程和RenderThread
中看到跟踪事件。在上图中,
Choreographer#doFrame
显示 UI 线程何时调用Choreographer
以协调动画、视图布局、图像绘制和相关过程。DrawFrames
显示RenderThread
何时形成并向 GPU 发出实际的绘图命令。如果您看到特别长的跟踪事件,您可以进一步放大并找出可能导致渲染缓慢的原因。上图显示 UI 线程中的
inflate
,这意味着应用正在花费时间膨胀布局。当您放大其中一个inflate
事件时,您可以找出每个 UI 组件花费的确切时间,如下所示。
了解更多
要了解有关如何减少卡顿的更多信息,请参阅卡顿的常见来源。