目录

应用冷启动慢

问题现象

首次打开应用或长时间未使用后重新打开应用时,从点击图标到应用主页面完全加载出来的时间过长,期间可能显示空白屏幕或加载动画。

背景知识

  1. 应用进程创建、初始化:该阶段主要是系统完成应用进程的创建以及初始化的过程,解码启动页图标。
  2. 启动应用、Ability:该阶段主要是加载资源,创建和初始化Application和Ability对象,加载依赖模块。
  3. Ability和AbilityStage生命周期:该阶段主要执行Ability和AbilityStage启动生命周期的回调。
  4. 加载绘制首页:该阶段主要是加载首页内容、测量布局、刷新组件并绘制显示。

问题定位

  1. 根据背景知识中网络环境质量相关信息排查问题发生前后的网络情况,若无异常则可排除网络质量差导致的应用启动慢。
  2. 在日志中搜索SetAsanEnabledEnv cold start app关键字,查看应用是否有设置ASan或HWASan,使用ASan或HWASan会有性能开销,适用于开发态调试压测场景,当进行性能测试或者应用上线时,需要把该功能关闭。
    05-10 11:07:09.086   5643-5643  C02C11/com.exa...tion/APPSPAWN  pid-5643  I   [asan_detector.c:176]SetAsanEnabledEnv cold start app com.example.myapplication
  3. 在日志中搜索onWillShow state|onShown state|onWillHide state|onHidden state关键字,如发现应用有长时间处于引导页(如下图所示中处于引导页长达15s),则推测在启动过程中主线程执行耗时操作或者应用业务逻辑设计导致启动时间长,可使用DevEco Profiler抓取该过程Trace进行分析。
    05-10 11:14:54.636   1356  1356 I C03922/com.example.myapplication/AceNavigation:  [(100000:100000:scope)] splash lifecycle change to onWillShow state.
    05-10 11:14:54.638   1356  1356 I C03922/com.example.myapplication/AceNavigation:  [(100000:100000:scope)] splash lifecycle change to onShown state.
    05-10 11:15:09.777   1356  1356 I C03922/com.example.myapplication/AceNavigation:  [(100000:100000:scope)] splash lifecycle change to onWillHide state.
    05-10 11:15:09.777   1356  1356 I C03922/com.example.myapplication/AceNavigation:  [(100000:100000:scope)] main lifecycle change to onWillShow state.
    05-10 11:15:09.777   1356  1356 I C03922/com.example.myapplication/AceNavigation:  [(100000:100000:scope)] splash lifecycle change to onHidden state.
    05-10 11:15:09.794   1356  1356 I C03922/com.example.myapplication/AceNavigation:  [(100000:100000:scope)] main lifecycle change to onShown state.

    在DevEco Profiler工具的分析结果中输入navDestinationName关键字找到进入引导页和进入主页时的Trace信息,分析该过程线程的运行状态。

    如该过程应用大部分时间处于休眠态(Sleeping),并且问题场景引导页停留时长相对固定(比如15s),则推测属于应用业务逻辑异常场景下设计相关问题(比如启动过程需要访问服务器获取数据,等待一段时间未有返回结果则停止等待,进入主页),需要排查应用业务逻辑。

  4. 如未搜到日志关键字,按以下图示步骤借助DevEco Profiler Launch分析抓取应用冷启动过程的耗时数据,查看Launch泳道中从Process Creating到First Frame - Render Phase过程耗时集中在哪一部分。

    • 如下图所示,如果耗时主要集中在应用进入前台阶段(UI Ability OnForeground),达到了1.2s。

      找到应用进程泳道,将应用进入前台阶段(UI Ability OnForeground)阶段框选起来查看该阶段应用线程的运行状态。如发现大多数时间都处于Running状态,可知应用在此处执行耗时操作。

      然后找到ArkTS Callstack泳道并点击,可以看到应用在该阶段的调用栈,查看调用栈中的函数名以及耗时占比情况可得到该部分耗时是由于Manager管理类在初始化间接调用了SDK.so的初始化方法,SDK初始化时间较长导致。

    • 如果耗时主要集中在UIAbility启动阶段(UI Ability Launching),如下图所示该阶段达到1.3s。

      找到应用主线程泳道,将UIAbility启动阶段框起来查看该阶段线程的运行状态和Trace信息,Trace信息从上到下显示表示上面Trace打点对应的函数直接或间接调用了下面Trace打点对应的函数,因此分析耗时原因主要分析下面的Trace打点。如发现大多数时间处于Running状态,耗时主要集中在H:SourceTextModule::Evaluate部分,则应用在启动过程时加载import的模块时耗时较多,导致应用启动慢。

    • 如果整体耗时与用户体验上差距较大,如下图所示,Process Creating到First Frame - Render Phase总耗时385ms,但用户体验加载时长达到3秒,该情况下应用可能长时间停留在启动页,一段时间后才跳转到主页,或者页面组件创建加载耗时较多,显示较慢。

      场景一:RN应用启动耗时:可点击主线程泳道,在Slice List中过滤组件创建的Trace关键字,在下图中可看到有RNSurface组件创建,可知该应用属于RN应用。RN应用中RNOH_JS线程负责构造节点树并提交到应用主线程完成渲染,可排查RNOH_JS线程。

      查看RNOH_JS线程Trace信息,可看到耗时主要集中在loadBundle部分(加载包含应用程序代码的JS文件,支持应用启动、更新等功能)。

      场景二:初始Web页面加载耗时:根据下表中对应关键字找到Trace点,计算Web加载各阶段耗时。

      阶段

      相关Trace关键字

      耗时

      Web组件初始化

      H:NWebImpl | CreateNWeb到H:NavigationControllerImpl::LoadURLWithParams | url=

      24ms

      导航流程

      H:NavigationControllerImpl::LoadURLWithParams到H:NavigationBodyLoader::StartLoadingBody

      274ms

      html解析以及重要子资源下载,页面加载完成

      H:NavigationBodyLoader::StartLoadingBody到H:RenderFrameImpl::didStopLoading

      466ms

      页面加载完成到开始显示网页

      H:RenderFrameImpl::didStopLoading到之后第一个SkiaOutputSurfaceImplOnGpu::SwapBuffers

      12ms

      总耗时

        

      776ms

      使用DevTools工具抓取页面加载过程,在“性能”选项卡下选择“主要”,可以看到有时长246ms的长任务耗时警告,整体耗时主要是在执行脚本,时间为500ms。

分析结论

应用冷启动慢的原因有:

修改建议