文章已获得原作者诚迈科技资深研发工程师-朱立民授权
一、引言
应用App的启动速度影响着用户的第一印象,良好的启动速度一定程度上促进APP的留存率和转化率提升。本文基于OpenHarmony4.0系统,结合公司实际应用启动未达D标问题进行分析和总结,经过一系列优化后,将music应用冷启动时间从1122.2ms缩减到835.6ms。
二、耗时检测
耗时检测参考华为厂商提供的视频拍摄测试方案,即方式一。反复进行视频拍摄对开发调试来说较麻烦,通过调研分析总结了抓log对比时间戳的粗估方案。
方式一、视频拍摄:
1.使用慢动作相机打开八倍速慢动作开始记录手指点击桌面设置应用图标到应用完全打开的全部过程;
2.在PC 端使用工具 avidemux2 打开上述拍摄的视频;
3.通过单帧播放记录起点帧数和终点帧数;
4.通过时延公式 (终点帧数 - 起点帧数 )x 1000 / 240 计算出响应时延;
5.重复上述步骤5次,计算平均值,如果初出现偏差较大结果,单次结果作废;
起点帧数:手指离开屏幕第一帧
终点帧数:界面完全加载完成第一帧
方式二、抓log对比时间戳:
从点击music桌面图标到应用界面完全加载完成第一帧,大概经过launcher处理、应用本身数据加载、应用数据渲染三个阶段。
首先,查看应用启动期间的log发现如下关键信息,将该时间戳作为launcher处理的时间起点。
其次,执行startAbility后,再进入music应用的onCreate回调方法。将应用本身数据加载的时间起点定义在onCreate方法的入口执行时。根据应用页面生命周期,可将应用本身数据加载的时间终点定义在onPageShow回调方法的出口执行时。
最后,因为应用数据渲染逻辑主要在框架层,对应用开发同学来说调研难度较大。但是,根据方式一中测量的应用启动总时间减去launcher处理时间和应用本身数据加载时间可大概估算应用数据渲染时间。
根据上述方式在music应用里统一以 'calculateAppIconPosition' 为TAG增加对应的log,这样可以方便的过滤应用启动全流程的log信息,增加log的代码片段:
- EntryAbility.ets
- const TAG: string = 'calculateAppIconPosition'
- onCreate(want:Want, launchParam: AbilityConstant.LaunchParam) {
- // globalThis.context = this.context
- Logger.info(TAG, `onCreate is called 0000`)
- GlobalThis.getInstance().setContext('context', this.context);
- console.log('Test->>EntryAbility->onCreate')
- let abilityInfo = this.context.abilityInfo;
- AppStorage.setOrCreate("bundleName", abilityInfo.bundleName)
- AppStorage.setOrCreate("context", this.context)
- Logger.info(TAG, `onCreate is called 1111`)
- }
-
- async onWindowStageCreate(windowStage: Window.WindowStage) {
- Logger.info(TAG, `onWindowStageCreate is called 1111`)
- let windowClass: window.Window = await windowStage.getMainWindow()
- ...
- // Creating an Audio Session.
- avSession.createAVSession(context, 'AudioAppSample', 'audio').then((session) => {
- GlobalThis.getInstance().setSession("currentSession",session);
- (GlobalThis.getInstance().getSession("currentSession") as avSession.AVSession).activate();
- }).catch((err: BusinessError) => {
- Logger.error(`createAVSession : ERROR : ${err.message}`);
- });
- Logger.info(TAG, `onWindowStageCreate is called 2222`)
- windowStage.loadContent('pages/MusicList', (err, data) => {
- if (err.code) {
- Logger.error('0x0000', 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
- return;
- }
- Logger.info('0x0000', 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
- });
- Logger.info(TAG, `onWindowStageCreate loadContent is called`)
- }
复制代码- MusicList.ets
- onPageShow() {
- console.log('calculateAppIconPosition Test->>MusicList->onPageShow 1111')
- this.monitorOrientationChanged();
- if (this.hasShowedPermissionsDialog) {
- this.queryAudioFileList();
- }
- console.log('calculateAppIconPosition Test->>MusicList->onPageShow 2222')
- }
复制代码