- 场景导入
应用冷启动加载完成时延慢,主要表现为一直卡在启动页和应用的首页长时间加载渲染,影响用户体验。
- 性能指标
2.1 性能衡量起始点介绍
冷启动加载完成时延的性能衡量的起点:点击应用图标离手冷启动加载完成时延的性能衡量的终点:应用的首页所有的占位符加载完成
- 问题定位流程
3.1 常规定位前置流程
3.1.1 查看操作录屏辅助定位
处理三方应用问题时,可以优先查看操作录屏,查看操作场景,看能否发现一些有助于定位的信息,比如页面布局、加载网络的动画时间等等。
3.1.2 Trace抓取
滑动帧率Trace抓取请参考【附录1: 冷启动Trace抓取方法】。
3.2 问题定位思路
应用冷启动过程:①离手 到 应用响应。表现为:点击后,应用桌面的响应的快慢,参考: 85ms②应用启动阶段 。应用还未送帧,使用启动页来提高用户体验,异常表现为,铺满全屏的启动页停留时间过长。参考: 600ms③首页加载阶段。应用帧送显后,启动页动效消失,首页开始加载渲染,到首页的所有占位符加载渲染完成。参考:1000ms。
(注:当流程图为否时,该阶段表示符合标准不需要分析)
3.2.1 在Trace确认起止点
起点确认:
H:DispatchTouchEvent type=1(大桌面ohos.sceneboard) -> CPU Running Trace(多模子系统mmi_service)-> H:service report(多模子系统mmi_service)
在大桌面泳道(ohos.sceneboard)搜索H:DispatchTouchEvent并且type=1(0,1,2分别代表按下,抬起,移动)的Trace点,该Trace点代表大桌面收到点击离手事件的Trace;
然后找到多模子系统泳道(mmi_service),找到H:DispatchTouchEvent前的一个CPU Running Trace,该Trace下有一个H:service report touchId:{id}, type: up [id: 0, x:{X}, y:{Y}]的Trace点,该Trace点的X,Y坐标和H:DispatchTouchEvent是对应的,且类型也是up,代表的是多模子系统收到点击离手事件的时间,H:service report这个Trace开始位置就是起点。
终点确认:(trace没有对应的打点,需要借助数帧视频确定)
终点距离应用响应的时间(949ms) = 4.065s(终点) - 3.116s(响应的时间)
trace上关键打点:(如上图)启动页打点:H:LAUNCHER_APP_LAUNCH_FROM_ICON, com.ohos.sceneboard(render_service 这个泳道动效打点)启动页消失动效打点:H:StartingWindowExitAnimation,当收到应用进程的第一帧时,启动页通过改变透明度消失。
**应用启动阶段和首页加载阶段的分界点:**我们可以粗略的将H:StartingWindowExitAnimation的起点作为分界点,准确的分界点是 H:PageRouterManager::RunPage 之后,应用的绘制第一帧那个位置。大体也在H:StartingWindowExitAnimation的起点的位置。
3.2.2 找问题点
3.2.2.1 相应阶段
响应阶段相对整个启动流程耗时相对较小,参考85ms。
3.2.2.2 应用启动阶段
快速定位 启动阶段是否有异常,如果 H:StartingWindowExitAnimation的起点的位置在启动页打点 之后,说明应用启动阶段异常。表现为:启动页停留时间长
启动阶段应用测主要是Ability资源加载界面布局(对应 EntryAbility.ets 文件,参考值 487ms), 应用主要做以下几件事,我们要看下面哪几件事耗时异常。若下面几个阶段耗时正常且在主线程并无发现其他阻塞主线程的操作,则需要系统侧帮忙分析。
表1-1
序号 | 所属泳道 | Trace点 | Trace点描述 |
---|---|---|---|
1 | 应用进程 | H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility | Ability对象创建及相关资源依赖模块加载 |
2 | 应用进程 | H:void OHOS::AbilityRuntime::UIAbilityThread::HandleAbilityTransaction | 该阶段主要是AbilityStage/Ability的启动生命周期,执行相应的生命周期回调 |
3 | 应用进程 | H:Napi complete, name:JsWindowStage::OnLoadContent | 加载首页内容 |
4 | 应用进程 | H:PageRouterManager::RunPage | 页面路由预处理 |
1~4序号对应的下面标记
可以看到 Ability资源加载界面布局 耗时837ms,明显超出基线值487ms,初步可以判断是启动阶段出了异常分析具体耗时原因,参考【4. 常见根因归档】
3.2.2.3 页面加载完成阶段
此阶段主要是加载页面:主要是应用侧 加载网络,渲染UI。页面加载完成可以参考 分析的问题点:
1.网络请求耗时过长等需要等待异步回调刷新UI(网络耗时过长或者延迟一段时间才请求网络),若有加载动画,表现为:加载动画持续时间长等。
2.页面的UI创建布局异常耗时,关注应用主线程的UI泳道。表现为:页面卡顿。
3.主线程可能执行耗时操作阻塞,这个需要关注ArkTS Callstack。表现为:页面卡顿。
第1点,我们通常可以通过安装hap,观察APP的启动过程和通过数帧视频观察app页面加载具体的耗时时间。例如下面案例【4.2 网络刷新导致冷启动加载完成超时】
第2点:具体参考案例【4.3.2.2.1 应用UI耗时案例】
- 常见根因归档
4.1 Ability的生命周期回调导致应用冷启动加载完成时较长
4.1.1 问题描述
应用冷启动中加载完成时延耗时1305ms
4.1.2 问题Trace特点
上文已快速定位启动阶段有问题( H:StartingWindowExitAnimation的起点的位置在启动页打点 之后)如图
具体问题如下:
问题1:对应的是H:SourceTextModule::Instantiate,H:virtual OHOS::ErrCode OHOS::AppExecFwk::BundleMgrProxy::GetBundleInfoForSelf(int32_t, OHOS::AppExecFwk::BundleInfo) 单次平均耗时2.5ms,调用22次,导致耗时过长,该接口是获取bundle信息,可以减少调用次数进行优化。如下图
问题2:H:virtual void OHOS::AbilityRuntime::JsUIAbility::OnStart(const OHOS::AbilityRuntime::Want &, sptrAAFwk::SessionInfo) 对应的ability 周期中onCreate的回调函数,其中H:napi_value OHOS::AbilityRuntime::JsUIAbility::CallObjectMethod耗时376ms, 这个是应用执行的js代码, 如下图
4.1.3 优化方案
-
GetBundleInfoForSelf 调用22次,原因是import hsp包时会获取hsp的路径信息,从而调用了GetBundleInfoForSelf。单hap场景下,模块推荐使用多har,不推荐使用hsp,hsp是采用动态加载,会增加编译耗时、响应时延会出现多次调用。
-
import过多的模块,耗时189ms, 需要应用排查,是否有些逻辑不需要放在启动过程中
-
应用排查ability生命周期中onCreate执行的耗时是否可以优化掉
4.2 网络刷新导致冷启动加载完成时间长
4.2.1 问题描述
应用冷启动中加载完成时延1881ms
4.2.2 Trace特点
超标281ms,快速定位启动阶段可能 没有问题( H:StartingWindowExitAnimation的起点的位置在启动页打点 之后),可以重点先看首页加载阶段。 如图
通过trace看出开启300ms动画。结合视频分析,发现有一个自动下拉刷新的功能
下拉刷新控件:只有下拉到一定的距离才会触发网络请求。
异常根因: 采用了 延时 网络请求的刷新控件,使得请求延后300ms
4.2.3 优化方案
冷启动时不要采用延迟加载网络组件,直接加载网络
4.3 多方面异常导致冷启动加载完成时间过长
4.3.1 问题描述
应用冷启动中加载完成时延3302 ms ,启动时间过长,冷启动体验不好。
4.3.2 Trace特点
(根据上文找到离手点对应的trace,然后根据数帧视频或者测试数据,找到终点位置)
根据H:StartingWindowExitAnimation的起点的位置在启动页打点 之后的距离,以及整个超标时长,我们可以快速判断,启动阶段和页面加载阶段都有异常。
4.3.2.1 启动阶段分析
根据章节3,我们确定启动阶段的起止点如下。
通过上面的trace我们发现,耗时主要在 H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility ,这块是 Ability对象创建及相关资源依赖模块加载。我们定位是应用的问题,需要应用侧帮忙确认资源加载的方式。 耗时总共509ms,如下图:
4.3.2.2 首页加载完成阶段
根据章节3,我们确定首页加载完成阶段的起止点如下。
分析应用的主线程,看应用做了哪些事,我们从三个角度来分析耗时。
4.3.2.2.1 应用UI耗时案例
看主线程创建更新UI的耗时,通过trace发现,应用有3个超长帧,共耗时420ms. 如下图
同时在应用的主线程中发现,应用在跳转到首页时调用2次H:PageRouterManager::LoadPage,然后分别创建了 序号1 和 序号2。 经过对比,发现这两帧组件也相同,怀疑是应用的代码bug。 同时在绘制UI时在H:aboutToAppear 执行了耗时操作,阻塞主线程。如下图
通过trace知道应用执行JS操作(如果ArkTS Callstack 有信息可以看下具体做了哪些操作)。
4.3.2.2.2 网络请求耗时过长等需要等待异步回调
通过数帧视频观察首页加载过程,首页加载有个网络加载动画,可以知道这个网络加载大概时间。首页还未渲染时,页面只有基本框架和 加载动画,通过trace z上的H:ohos.animator onframe. duration:20000, curve:linear的打点,我们可以确定下面是网络请求的时间。耗时1.1s
发现在主线程有一大空段,怀疑是应用在等待异步回调,需要确认是否应用代码问题。如图
4.3.3 优化方案
启动阶段优化资源加载
建议优化网络请求的业务,可以先显示部分重要数据
优化UI创建,查看跳转首页逻辑是否有bug
附录1: 冷启动Trace抓取方法
Step1:打开DevEco Studio的Profiler(下图1) -> 选择设备进程(下图2)-> Frame模式(下图3)-> Create Session(下图4)-> 启动录制(下图5)。
注意:第二步选择进程时不要选择要录制的进程,因为要录制的进程需要处于未启动状态,这里是通过录制其他进程间接录制目标进程的启动Trace信息。
Step2: 启动录制后,在设备上点击应用图标启动要录制的目标应用,等到应用首页加载后,点击停止结束录制。
Step3:录制完成后会工具会分析展示Trace数据。
附录2: 冷启动加载完成时延Trace点解读
以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下:
内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
鸿蒙【北向应用开发+南向系统层开发】文档
鸿蒙【基础+实战项目】视频
鸿蒙面经
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!