同页面内抛滑操作响应时延问题分析思路&案例
1. 场景导入
抛滑操作响应时延:应用页面内手指抛滑场景下,手指滑动,到页面发生变化的时间。
2. 性能指标
2.1 性能指标介绍
a.应用或元服务内滑动操作响应时延应 ≤ X。
b.时间起点:手指滑动;时间终点:界面发生变化。
c.滑动速度:大于300ms/s;滑动次数:每次半屏,连续3次。
S标 | A标 | B标 |
80ms | 120ms | 180ms |
2.2 性能衡量起始点介绍
抛滑操作响应时延:应用页面内手指开始滑动,到页面发生变化的时间。
响应时延计算公式 响应时延=硬件耗时+软件耗时(整个耗时,包含我们在trace上看的软件的耗时,机器本身的一个硬件耗时,一般硬件耗时大概在30ms左右,在trace上的起点到终点的时间加上30ms左右的硬件耗时和测试给出的实际耗时能对的上即可。)
起点:手指接触屏幕并开始滑动;
终点:页面发生变化;
3. 问题定位流程
3.1 常规定位前置流程
处理三方应用问题前首先需要先和三方应用及测试确认当前问题场景的静态KPI标准(S标):
- 三方应用:和三方应用确认问题场景是否认可该标准,如不认可,相关问题需评审关闭。
- 测试:和测试确认是否按照静态KPI标准执行的测试,测试步骤和性能衡量是否准确。
处理三方应用问题时,可以优先查看操作录屏,查看操作场景,看能否发现一些有助于定位的信息,比如页面滑动是否卡顿等。
页面滑动Trace抓取请参考"附录1: 页面滑动Trace抓取方法"。
3.2 问题定位思路
抛滑场景处理流程如下:
起点 mmi_service 对应的坐标开始变化的点 。(例如:H:service report touchId:26899, type: move [id: 0, x:629, y:2117],其中type:down 表示手指按下,move表示手指滑动,up表示手指抬起)
- 点击搜索。
- 在输入框中输入mmi_service。
- 点击跳转到mmi_service 泳道。
从上图可以看出,第一个点和第二个点的坐标已经发生了变化。
终点页面变化第一帧对应RS HardwareThread:CommitAndReleaseLayers 的终点。(对应图标5代表的点。)
终点Trace查找顺序:H: service report touchId: type:(多模输入mmi_service) -> H:FlushMessages(应用)-> H:SendCommands(应用)-> H:MarshRSTransactionData(应用) -> H:RSMainThread::ProcessCommandUni(RS服务render_service)-> H:ReceiveVsync(RS服务render_service)-> H:RSHardwareThread(RS送显线程RSHardwareThrea)
序号 | 泳道 | Trace | 描述 | 参数说明 |
1 | mmi_service | H:service report touchId:2242, type: down [id: 0, x:709, y:2162] | mmi_service在屏幕上坐标开始变化的点, | |
2 | 应用 | H:FlushMessages && H:SendCommands | 通知图形侧进行渲染 | |
3 | 应用 | H:MarshRSTransactionData cmdCount: transactionFlag: | 通知图形侧进行渲染 | |
4 | render_service | H:RSMainThread::ProcessCommandUni && ReceiveVsync | 图形接收Vsync信号 | |
5 | RSHardwareThread | H:RSHardwareThread:CommitAndReleaseLayers | GPU渲染完成提交RSHD进行合成 |
(1)选取起止点这一区间,查看Frame 泳道,往后查看Frame应用侧帧渲染情况,是否出现异常帧、超长帧。如下图可以看出第560帧为超长帧,超长帧的耗时也会导致整个响应时延不达标。
(2)超长帧的场景一般需要结合应用主线程泳道查看组件渲染情况,具体分析参考4.1.2应用帧耗时分析。
(3) 选取起止点这一区间,查看ArkTS Callstack调用栈,查看耗时任务,如发现耗时任务,则继续查看耗时原因,一般结合应用进程UI主线程查看。
Symbol Name | 含义 |
initialRenderView | 表示页面初始化 |
Program | 代表程序执行进入纯native代码阶段,该阶段无JS代码执行,也无JS调用native或者native调用JS情况(需要切换到Callstack泳道看具体的调用栈信息,一般很难通过这里分析出有效的信息)。 |
(BUILTIN) | 表示JS标准库接口,Native实现,虚拟机提供 |
anonymous | 匿名函数,具体需要查看代码确定此处是什么逻辑 |
(4)选取起止点这一区间,查看Callstack的Native调用栈,查看耗时任务,如发现耗时任务,则继续查看耗时原因,一般结合应用进程UI主线程查看。
(5)结合使用DevEco Testing 的UIViewer 可以看出组件的层级关系,逐级展开用于分析组件复杂度。冗余的嵌套会带来不必要的组件节点,加深组件树的层级,导致应用帧耗时较长,从而影响响应时延。
滑动响应时延类问题主要根据3.2.2章节内容定位到问题点,如果想了解更详细的滑动时延范围内的Trace流程解读,见附录2:滑动响应时延Trace点解读。
4. 典型问题
4.1 自定义布局计算以及页面层级嵌套导致达不到S标
问题描述:应用内向上抛滑浏览页面,响应时延96,S标80ms,超时16ms
序号 | 泳道 | Trace | 描述 | 参数说明 |
1 | mmi_service | H:service report touchId:type: | mmi_service在屏幕上坐标开始变化的点, | |
2 | 应用 | H:FlushMessages && H:SendCommands | 通知图形侧进行渲染 | |
3 | render_service | H:ReceiveVsync | 图形接收Vsync信号 | |
4 | RSHardwareThread | H:RSHardwareThread:CommitAndReleaseLayers | GPU渲染完成提交RSHD进行合成 |
(上图中 1 为起点,4为终点)
分析数据1.测试数帧实际结果是102ms ,在以上trace可以看到,应用第一帧,上屏时间在66ms左右, 加上30多毫秒的硬件耗时,和录屏102ms能对应上。所以当前trace上页面发生变化的帧是对应的应用第一帧。所以终点应该是应用第一帧对应的RSHardwareThread 对应的CommitAndReleaseLayers的结束点,如上图。2.从Trace上看,总体是由于滑动开始的第一帧应用侧耗时过长 (31ms),导致rs的执行延迟(错过了VSync信号,应用帧结束距离rs帧开始4.9ms),从而导致整体耗时过长。
第一帧后半段,WaterFlow 的 Item 中包含大量 LightArtViewContainer 、LightArtBlockView (14个左右)等组件,还有少量 LightArtImageView、LightArtLabelView,远超过能在App界面上看到的元素的个数,因此推测是 Item 的组件太多,导致布局计算复杂、耗时过长。JSMeasure 说明使用了自定义布局 onMeasureSize,增加了布局计算耗时。
后面有一段ExecuteJS, 这里可以查看ArkTS Callstack, Request 中computeApiSign耗时较长,有16ms; 这里需要应用侧排查是否可以优化。
建议应用侧简化组件结构,减少不必要的组件,减少多余嵌套容器;优化布局的方式。
附录一 Trace抓取方式
(1)电脑连接上设备,在DevEco Studio上打开Profiler,设备上运行需要测试的应用,在设备列表选择设备,选择要测试的应用,和主进程。
(2)创建Frame模板,并点击录制,待泳道都进入到recording状态后,在应用上复现测试场景。
附录二 场景通用Trace流程点说明
H:APP_LIST_FLING :List的单次抛滑过程,可以通过应用进程下的。H:APP_LIST_FLING泳道标识。
滑动场景通用流程
抛滑首帧响应时延 | 起点 | 终点 | 基线 | 首问责任领域 |
input阶段 | 首个坐标变化对应irq/thp | 1首个坐标变化对应mmi_service | 多模 | |
TP事件分发 | 1首个坐标变化对应mmi_service | 2首次送显FlushMessage结束 | 应用 | |
首帧渲染显示 | 3找过对应的RS帧ReceiveVsync起始点 | 4H:RSHardwareThread::CommitAndReleaseLayers的结束点 | 图形 |
(表格中的1~4对应下图中的trace点信息)
序号 | 泳道 | Trace | 描述 | 参数说明 |
1 | mmi_service | H:service report touchId:2242, type: down [id: 0, x:709, y:2162] | mmi_service在屏幕上坐标开始变化的点, | |
2 | 应用 | H:FlushMessages && H:SendCommands | 通知图形侧进行渲染 | |
3 | render_service | H:ReceiveVsync | 图形接收Vsync信号 | |
4 | RSHardwareThread | H:RSHardwareThread:CommitAndReleaseLayers | GPU渲染完成提交RSHD进行合成 |
注意:未提交的帧的SendCommands下方无H:MarshRSTransactionData Trace点。
总结: 从上面的流程图可以看出,APP_LIST_FLING 泳道下的首个FlushMessages为应用送显的FlushMessages. 因此可以通过APP_LIST_FLING 快速定位滑动响应过程trace 点。
序号 | 泳道 | Trace | 描述 |
1 | mmi_service | H:service report touchId:2242, type: down [id: 0, x:709, y:2162] | mmi_service在屏幕上坐标开始变化type 为move 的点 |
2 | 应用 | H: APP_LIST_FLING | 滑动过程 |
3 | render_service | RSHardwareThread 首个 CommitAndReleaseLayers | rs 渲染线程 |