一、简介
应用启动可以分为冷启动和热启动,冷启动指的是应用启动,后台没有该应用的进程,系统会重新创建应用进程。热启动是当应用程序已经在后台运行,用户再次打开应用程序时,系统可以直接从内存中加载并继续之前的状态。当应用冷启动时延大于1100ms时,可以认为是应用启动缓慢。
二、Profile Launch分析启动耗时
Profiler Launch可以拆解应用冷启动过程,抓取不同阶段的耗时数据。
从上图可以看到Launch将应用的冷启动过程拆解为以下几个阶段:
- Create Process:应用进程创建阶段,对应的trace打点为AbilityManagerService::StartAbilityMissionListManager::StartAbilityLocked##{bundleName}
- Application Launching:应用启动阶段,对应的trace打点为AppMgrServiceInner::AttachApplication##{bundleName}
- UI Ability Launching:UIAbility启动阶段,对应的trace打点为MainThread::HandleLaunchAbility##{bundleName}
- UI Ability OnForeground:应用进入前台阶段,对应的trace打点为AbilityThread::HandleAbilityTransaction
- First Frame - App Phase:App首帧渲染提交阶段,对应的trace打点为H:ReceiveVsync,H:MarshRSTransactionData
- First Frame - Render Phase:RS首帧渲染提交阶段,对应的trace打点为H:ReceiveVsync,H:RSMainThread::ProcessCommandUn
- EntryAbility:应用启动之后的阶段,渲染完成,首页显示。
从Create Process阶段开始到First Frame - Render Phase阶段,这段时间可以看作是应用的冷启动时间,在Launch泳道到上,使用鼠标左键拖动这两个阶段的区间,可以看到应用冷启动时间。
2、1 Profile Launch检测启动耗时
toManyTask(): void {
let count = 0;
while (count < LARGE_NUMBER) {
count++;
}
}
将上面的耗时代码分别放到AbilityStage的onCreate、EntryAbility的onForeground、index.ets的aboutToAppear。这样的话,启动时候就有三处耗时,看看Profile Launch能否检测到这三处耗时。按照下图中的步骤分析分析启动耗时。
如下图所示,当分析完成后,就能看到UI Ability Launching,UI Ability OnForeground、EntryAbility这三个阶段占据应用冷启动过程的大部分时间。
如下图所示,UI Ability Launching耗时6秒。
如下图所示,UI Ability OnForeground耗时4秒。
如下图所示,Entry Ability耗时1秒。
经过上面的步骤,就能知道各个阶段的耗时,但是还不知道具体是哪段代码耗时。如下图所示,ArkTS Callbackstack清楚的列出了耗时代码所在的方法以及所在的文件,双击方法名即可跳转到耗时代码处。
也可以打开火焰图,火焰图也可以定位到耗时代码,可以更直观的看出热点函数的耗时情况。
将耗时代码放到子线程后,从Create Process到First Frame - Render Phase执行结束才263毫秒,从Create Process到Entry Ability执行结束才1.1秒。
三、启动优化方案
- 非冷启动必须的服务或模块延迟加载。
- 将网络请求提前至AbilityStage/UIAbility生命的onCreate()生命周期回调函数中,将首刷或二刷的时间提前,减少用户等待时间。
- 启动页图标startWindowIcon分辨率建议不超过256px*256px。
- 在AbilityStage、UIAbility和自定义组件的生命周期回调函数中不建议直接执行耗时任务,比如复杂的计算任务、同步文件读写等耗时任务,建议通过异步任务延迟处理或者放到其他线程执行。
- import模块按需加载,移除初始化阶段不需要的模块导入,考虑动态加载耗时的模块。
- 减少使用嵌套export *全量导出和import *全量引用。
- 拆分HAR包导出文件或导入冷启动相关文件时使用全路径,减少应用冷启动中.ets文件执行耗时。
- 避免多个HAP/HSP对相同HAR的引用。
- 单HAP场景下,模块推荐使用多HAR,不推荐使用HSP。
- 通过使用合理的布局结构、使用懒加载等UI优化方法来减少首帧绘制时间。
- 使用本地存储首页数据,减少首帧展示完成时延,减少用户可见白屏或白块时间。