丢帧问题概述
应用丢帧通常指的是在应用程序的界面绘制过程中,由于某些原因导致界面绘制的帧率下降,从而造成界面卡顿、动画不流畅等问题。以60Hz刷新率为例子,想要达到每秒60帧(即60fps)的流畅体验,每一帧需要在16.7ms内完成,如果超过16.7ms未完成渲染,就可能会出现丢帧。
本文主要是以Trace数据为切入点进行分析,相应的工具可以使用DevEco Studio内置的[Frame Profiler]。
本文将主要介绍以下内容,来帮助开发者解决应用丢帧问题:
- 丢帧问题原理
- 发现丢帧问题
- 丢帧问题分析
- 常见丢帧问题
- 丢帧问题优化建议
丢帧问题原理
在了解如何定位应用丢帧问题之前,开发者需要简单了解HarmonyOS中图形渲染的流程,便于在遇到卡顿时可以分析卡顿可能出现的阶段和原因。
在HarmonyOS中,图形系统采用了统一渲染的模式,遵循着一个典型的流水线模式,以90Hz刷新率为例,每个Vsync周期是11.1ms,整个过程如下图所示。如果是60Hz,每个Vsync的周期是16.7ms;如果是120Hz,则每个Vsync的周期是8.3ms。
图1 90Hz刷新率渲染流程
在整个渲染流程中,首先是由应用侧响应消费者的屏幕点击等输入事件,由应用侧处理完成后再提交给Render Service,由Render Service协调GPU等资源处理后,再将最终的图像统一送到屏幕上进行显示。
- 应用侧(App)处理用户的屏幕点击等输入事件,生成当前界面描述的数据结构。其中,界面描述数据包括UI元素的位置,大小,资源,UI元素的绘制指令,动效属性等。
- RenderService(渲染服务部件)是图形栈中负责界面内容绘制的模块,其主要职责就是对接ArkUI框架,支撑ArkUI应用的界面显示,包括控件、动效等UI元素。RenderService的RenderThread线程在Vsync下触发UI绘制,绘制过程包含3个阶段:Animation动效,Draw描画和Flush提交。
- Display是显示屏幕的抽象概念,可以是实际的物理屏也可以是虚拟屏。
其中应用侧的渲染流程如下图所示,了解ArkUI的渲染流程有助于我们定位应用侧的卡顿问题出现在哪个环节:
图2 ArkUI渲染管线结构与Frame Insight性能打点
- Animation:动画阶段,在动画过程中会修改相应的FrameNode节点触发脏区标记,在特定场景下会执行用户侧ets代码实现自定义动画;
- Events:事件处理阶段,比如手势事件处理。在手势处理过程中也会修改FrameNode节点触发脏区标记,在特定场景下会执行用户侧ets代码实现自定义事件;
- UpdateUI:自定义组件(@Component)在首次创建挂载或者状态变量变更时会标记为需要rebuild状态,在下一次Vsync过来时会执行rebuild流程,rebuild流程会执行程序UI代码,通过调用View的方法生成相应的组件树结构和属性样式修改任务。
- Measure:布局包装器执行相关的大小测算任务。
- Layout:布局包装器执行相关的布局任务。
- Render:绘制任务包装器执行相关的绘制任务,执行完成后会标记请求刷新RSNode绘制
- SendMessage:请求刷新界面绘制。
在整个处理流程中,应用侧和Render Service侧都有可能出现卡顿导致最终用户观测到丢帧的可能,我们分别将这两种情况命名为AppDeadlineMissed和RenderDeadlineMissed。一般而言,前者可能是应用逻辑处理代码不够高效导致的,后者可能是界面结构过于复杂或者GPU负载过大等原因导致的。这两个故障模型通过Frame模板都可以直观地看到。相应的故障模型如下面两幅图所示。
图3 应用卡顿导致丢帧的故障模型
图4 Render Service卡顿导致丢帧的故障模型
丢帧问题思路分析
补充了图像渲染流程的基本知识和丢帧的故障模型后,接下来我们介绍丢帧问题的分析思路,下图展示了解决丢帧问题的简要流程:
图5 丢帧问题处理流程
从上图可以看到处理丢帧问题一般需要以下四个步骤:
- 识别卡顿:首先使用AppAnalyzer检测应用是否存在性能问题,如果检测存在丢帧问题,然后使用Frame Profiler、SmartPerf Host等工具录制Trace,查看应用平均帧率、丢帧率等,同时查看丢帧发生的位置。
- 分析丢帧原因:首先查看CPU调用判断系统是否存在异常,如果判断系统异常开发可以通过[在线提单]的方式进行反馈;如果系统没有异常,可以继续分析Trace查看卡顿帧的详细信息。最后查看函数调用栈,查看是否存在耗时函数。
- 选择优化方案:根据步骤2分析的丢帧原因,选择适合的优化方案。
- 验证优化效果:优化完成后需要重新测试验证丢帧问题是否得到解决,这里可以再次通过步骤1来确认优化效果
接下来本文将以“HMOS世界”应用的首页列表为例,介绍如何通过Frame分析、定位、解决卡顿问题的全过程。为了便于演示这个长列表的调优过程,这个列表初始加载了1000条数据。
我们在滑动列表的过程中,随着时间的推移,我们可以感觉到越来越卡顿,接下来我们将介绍如何分析并解决这个卡顿问题。
图6 ”HMOS世界”首页长列表示意图
第1步:识别丢帧
使用AppAnalyzer检测性能问题
首先使用AppAnalyzer工具进行性能问题检测,AppAnalyzer是DevEco Studio中提供的检测评分工具,用于测试并评价HarmonyOS应用或元服务的质量,能快速提供评估结果和改进建议,当前支持的测试类型包括兼容性、性能、UX测试和最佳实践等。因为本文主要是介绍丢帧问题的分析,所以下面重点介绍了使用AppAnalyzer对列表滑动响应和滑动过程中的流畅性能检测。
-
启动DevEco Studio,连接设备,打开应用。
-
单击菜单栏Tools > AppAnalyzer。
-
在AppAnalyzer页面Module选择框选择应用/服务工程模块。
-
根据应用的类别选择Category。
-
选择Rules,这里选择Benchmark(性能套餐),勾选”Fast Response to In-app Swipes”(应用内滑动操作响应快)、“Smooth In-app Swiping“(应用内滑动过程流畅)和“Smooth In-app Transitions“(应用内转场操作流畅)。
-
-
点击Start启动检测,检测过程中,手机需要保持解锁亮屏状态。
-
工具会先对应用功能进行自动检测,开发者不需要进行操作,在自动检测结束后需要根据提示手动遍历应用功能。
-
自动检测和手动遍历完成后点击Stop停止测试任务。
-
-
获得检测结果,下面列举了检测通过和未通过的示例。
-
检测通过示例,如下图所示,无异常信息。
-
检测未通过示例,例如下图结果,有多项检测未通过。
点击左侧的菜单栏对应的选项,可以查看异常的具体信息,这里以”Fast Detection Of Smoothness During Sliding”选项为例,应用滑动时的卡顿率应该小于5ms/s,但是示例中有多帧超时达到8.49ms,存在进一步优化的空间
-
录制Frame模板
发现卡顿丢帧问题后创建Frame模板录制,在录制期间复现卡顿丢帧场景。
录制完成后,在时间轴上拖动鼠标选定要查看的时间段,这里选择了一个2.5s的时间区段。选中Frame主泳道,查看下