基于ArkUI页面切换类点击操作完成时延问题分析思路&案例
1、场景导入
ArkUI页面切换类点击操作完成时延,应用的UI界面有许多需要和用户交互的地方,按钮的点击是很常见的一种。点击按钮应用转场进入下一个页面。应用的点击完成时延,是从点击应用离手开始到转场页面所有占位符加载完成。
2、性能指标
2.1、性能指标介绍
应用或元服务内点击操作完成时延s标为900ms,允许误差范围5%。
2.2、性能衡量起止点介绍
通过Avidemux工具查看视频来确定点击完成时延起点和终点,然后计算出整个耗时的时间,计算出来的这个时间在后面分析trace的时候会用到。
3.问题定位流程
3.1、 常规定位前置流程
处理三方应用问题前首先需要先和三方应用及测试确认当前问题场景的静态KPI标准(S标):
- 三方应用:和三方应用确认问题场景是否认可该标准,如不认可,相关问题需评审关闭。
- 测试:和测试确认是否按照静态KPI标准执行的测试,测试步骤和性能衡量是否准确。
处理应用问题时,可以优先查看操作录屏,看看具体的操作场景,能否发现一些有助于定位的信息,还需要自己在单框架的手机上安装hap包运行应用操作观察帮助定位。例如可以初步看出网络请求的时间是否合理,应用布局的复杂度等。
点击操作完成时延Trace抓取请参考附录1: 点击操作完成时延Trace抓取方法。
3.2、 问题定位思路
点击操作完成时延类问题的通用定位思路为先确认时延起止点,然后看起止点时延是否超900ms,没有超过就是达标,如果超过900ms,就需要进一步分析trace看看耗时主要发生在什么地方,然后确定是系统问题还是三方问题,然后对齐问题。处理流程如下图:
起点确认
搜索dispatchtouchevent,找到type=1的那个dispatchtouchevent,就是点击抬手起点。
Trace点名称 | 含义 | 问题定位作用 |
DispatchTouchEvent , type=1 | 手指点击后离手 | 作为点击完成 |
终点确认
点击操作完成时延的终点位置在trace上没有明确的trace点,需要按照2.2里面所介绍的方法确定终点。然后根据视频上数出来的加载完成的整个耗时在trace上拉相同的时间找到终点位置。这样就有了整个完成时延的耗时区间。并在Markers泳道做好标记。
1. ArkTS Callstack子泳道ArkVM是需要最优先查看耗时情况的泳道,可以看到ArkTS侧一些方法的耗时,优先分析耗时最长的调用栈(program除外,program代表程序执行进入纯native代码阶段,该阶段无JS代码执行,也无JS调用native或者native调用JS情况,需要切换到Callstack泳道看具体的调用栈信息,一般很难通过这里分析出有效的信息),逐级展开,可以看到具体耗时的文件。
Symbol Name | 含义 |
initialRenderView | 表示页面初始化 |
Program | 代表程序执行进入纯native代码阶段,该阶段无JS代码执行,也无JS调用native或者native调用JS情况(需要切换到Callstack泳道看具体的调用栈信息,一般很难通过这里分析出有效的信息)。 |
rerender | 主要发生在页面更新的场景 |
(BUILTIN) | 表示JS标准库接口,Native实现,虚拟机提供 |
aboutToAppear | 组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行 |
aboutToDisappear | aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定 |
anonymous | 匿名函数,具体需要查看代码确定此处是什么逻辑 |
2. 还可以查看 Frame泳道里面的应用主线程子泳道,这个泳道显示app侧帧数据,这个里面如果有出现红色的帧表示异常,可以查看红色帧的耗时,如下图所示的第82帧。
每帧的预期耗时(ms) = 1000ms / 帧率 。如下图,鼠标点击选中超长帧,可以看到该帧的预期耗时Expected Duration 为8ms 276us,说明帧率是120,而实际耗时为93ms394us,远超预期耗时,就是超长帧,超长帧的耗时也会导致整个点击完成时延不达标。
1. 接着可以查看Callstack泳道(该泳道显示Native函数调用泳道,可以看到native函数调用栈)里面的应用主线程子泳道以及有内容显示的WorkerThread子泳道耗时情况。
2. 选中ArkUI Component泳道,可以看到组件的数量以及耗时,重点关注相对于其他组件耗时比较久的组件。
3. DevEco Testing 的UIViewer 可以看出组件的层级关系,逐级展开用于分析组件复杂度。冗余的嵌套会带来不必要的组件节点,加深组件树的层级,在创建和布局阶段会耗时比较久。
4. 如果点击页面切换的过程中有加载的loading动画,可以通过H:Animator 泳道,看出动画耗时,动画的耗时基本就是网络请求的耗时。
4、常见根因归档
4.1、 因在点击操作的转场过程中加载资源、解析资源过长导致点击完成时延不满足
1.用DevEco Studio 的profiler的frame模板去抓trace,利用dispatchtouchevent type = 1 确定起点,通过视频数帧可以得出这个点击完成时延耗时2800ms,在trace上圈出这段时间来分析耗时。在ArkTS Callstack子泳道ArkVM并没有发现耗时,于是查看其他泳道,发现Callstack里面的子泳道workerThread有耗时异常。
2.把耗时的栈一层层展开,发现是在cocos2d::experimental:AudioDecoder 里面耗时1s135ms,耗时超过s标需要优化。在csloder里面耗时400ms左右,相对于s标900ms来说占比较大,有优化空间,怀疑是在点击跳转的期间在加载资源。
- rawfile加载资源比较耗时,尝试改变加载资源的方式。加载方式参考链接文档https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/resource-categories-and-access-0000001774119914#section694911752315
- AudioDecoderMp3: decodeTOPCM 耗时很长,音频解码耗时较多。
需要优化资源加载方式和音频解码优化。
4.2、 网络请求耗时久导致点击完成时延不满足
点击完成时延s标900ms,通过视频可以看出点击后有一个网络请求的loading图,于是查看Trace的H:Animator 泳道,通过Trace看出网络请求耗时 637ms,和s标相比较占比很大,此时网络耗时是导致不达标的主要原因。
4.3、 组件使用不合理导致点击完成时延不满足 s标900ms, 实测999ms
1.查看Frame里面的应用主线程泳道,发现在点击事件后面有一帧超长帧。在Trace上圈出这段时间,再查看Trace的ArkTS CallStack泳道,其中VipImageView耗时 35ms,对应每个ListItem中加载的4张图片,parseURL耗时14.5ms;查看视图层级发现一个Image被包装了5层容器。可以考虑减少解析url的耗时,以及减少包装Image的层级。
2.接着查看应用主线程泳道,发现在网络请求动画结束后面(网络请求示例在4.2中已展示)开始刷新列表内容,会看到有大量组件初始化的过程,还会调用很多aboutToDeleted,说明有旧的组件被移除。
下图为上图中红框展开的详细图,可以看出有很多的aboutToDeleted事件。
圈出有很多aboutToDeleted这段时间,切换到ArkVM泳道,可以看出每个aboutToDeleted所耗的时间。可以看出最多的aboutToDeleted耗时4ms左右,最少的也有几百us,再加上这个地方有大量的aboutToDeleted,累积起来耗时就比较多。可以用Resuable进行优化,从而达到组件的复用,避免创建和析构大量组件。
3.上述两步已经找出完成时延不达标的主要原因所在,接下来还可以利用 DevEco Testing 的UIViewer工具去判断组件是否有冗余的容器嵌套,冗余的嵌套会带来不必要的组件节点,加深组件树的层级,在创建和布局阶段会耗时比较久。
- 组件没有复用,给组件加上@Resuable标识自定义组件具备可复用的能力](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/performance/list-perf-improvment.md)
- 组件层级嵌套太多,去掉多余的层级。
附录1:点击操作完成时延Trace抓取方法
1. 安装应用hap包,或者从市场下载应用。
2. 关掉手机上所有应用,打开需要抓trace的应用,将页面切换到需要分析的点击操作完成时延的场景。
3. 在profiler中选择需要抓trace的应用,并选取frame模板,然后create session。然后点击开始录制。
4. 当处理recording状态的时候 ,点击按钮响应等到页面切换完成且占位符加载完成停止录制。
5. 完成录制等待analyzing。