鸿蒙性能优化之启动优化

197 阅读4分钟

一、简介

  应用启动可以分为冷启动和热启动,冷启动指的是应用启动,后台没有该应用的进程,系统会重新创建应用进程。热启动是当应用程序已经在后台运行,用户再次打开应用程序时,系统可以直接从内存中加载并继续之前的状态。当应用冷启动时延大于1100ms时,可以认为是应用启动缓慢。

二、Profile Launch分析启动耗时

  Profiler Launch可以拆解应用冷启动过程,抓取不同阶段的耗时数据。

image.png   从上图可以看到Launch将应用的冷启动过程拆解为以下几个阶段:

  1. Create Process:应用进程创建阶段,对应的trace打点为AbilityManagerService::StartAbilityMissionListManager::StartAbilityLocked##{bundleName}
  2. Application Launching:应用启动阶段,对应的trace打点为AppMgrServiceInner::AttachApplication##{bundleName}
  3. UI Ability Launching:UIAbility启动阶段,对应的trace打点为MainThread::HandleLaunchAbility##{bundleName}
  4. UI Ability OnForeground:应用进入前台阶段,对应的trace打点为AbilityThread::HandleAbilityTransaction
  5. First Frame - App Phase:App首帧渲染提交阶段,对应的trace打点为H:ReceiveVsync,H:MarshRSTransactionData
  6. First Frame - Render Phase:RS首帧渲染提交阶段,对应的trace打点为H:ReceiveVsync,H:RSMainThread::ProcessCommandUn
  7. 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能否检测到这三处耗时。按照下图中的步骤分析分析启动耗时。

image.png

image.png   如下图所示,当分析完成后,就能看到UI Ability Launching,UI Ability OnForeground、EntryAbility这三个阶段占据应用冷启动过程的大部分时间。 image.png   如下图所示,UI Ability Launching耗时6秒。 image.png   如下图所示,UI Ability OnForeground耗时4秒。 image.png   如下图所示,Entry Ability耗时1秒。 image.png   经过上面的步骤,就能知道各个阶段的耗时,但是还不知道具体是哪段代码耗时。如下图所示,ArkTS Callbackstack清楚的列出了耗时代码所在的方法以及所在的文件,双击方法名即可跳转到耗时代码处。 image.png   也可以打开火焰图,火焰图也可以定位到耗时代码,可以更直观的看出热点函数的耗时情况。 image.png

  将耗时代码放到子线程后,从Create Process到First Frame - Render Phase执行结束才263毫秒,从Create Process到Entry Ability执行结束才1.1秒。 image.png

三、启动优化方案

  • 非冷启动必须的服务或模块延迟加载。
  • 将网络请求提前至AbilityStage/UIAbility生命的onCreate()生命周期回调函数中,将首刷或二刷的时间提前,减少用户等待时间。
  • 启动页图标startWindowIcon分辨率建议不超过256px*256px。
  • 在AbilityStage、UIAbility和自定义组件的生命周期回调函数中不建议直接执行耗时任务,比如复杂的计算任务、同步文件读写等耗时任务,建议通过异步任务延迟处理或者放到其他线程执行。
  • import模块按需加载,移除初始化阶段不需要的模块导入,考虑动态加载耗时的模块。
  • 减少使用嵌套export *全量导出和import *全量引用。
  • 拆分HAR包导出文件或导入冷启动相关文件时使用全路径,减少应用冷启动中.ets文件执行耗时。
  • 避免多个HAP/HSP对相同HAR的引用。
  • 单HAP场景下,模块推荐使用多HAR,不推荐使用HSP。
  • 通过使用合理的布局结构、使用懒加载等UI优化方法来减少首帧绘制时间。
  • 使用本地存储首页数据,减少首帧展示完成时延,减少用户可见白屏或白块时间。