一、背景
提到性能优化,跟页面相关的就两个指标:冷启动时长和页面 FPS 冷启动时长用来表征用户在首次打开页面时到页面渲染完成的耗时,很明显这个耗时越短,用户的体验将会越好。而 FPS 则表示页面渲染的帧率,FPS 越高,表示页面交互越流畅。所以我们的目标是:冷启动时长得低,FPS 得高,这样就表示用户能快速进入页面并且愉快的交互了。
随着业务复杂度的增加,发现页线上的冷启动耗时有点差强人意,于是就有了这一波发现页的冷启动优化。
二、思路
基于以前优化经验,迅速整理出了优化思路,并形成如下脑图:
三、优化结果
1)低端机自然冷启到页面渲染完毕进 1s,目前实验室数据 892ms,行业对比数据如下:
2)低端机 push 冷启到视频起播进 5s,优化前后对比效果如下:
四、主路径梳理
针对发现页,对其启动主路径梳理如下:
五、懒加载
依赖阿里中间件 AppMonitor 的页面完成的回调接口,通过将所有可以懒加载的任务用 MonitorTask 包装后抛给 PageMonitorTaskDomain 在合适的时机执行,如:当 page 处在可交互的状态时执行:
几个主要的懒加载项:
1)Tab 动画;
2)Poplayer;
3)卡片推荐任务;
4)Viewpager 左右 Tab 懒加载;
5)各种业务(换肤、福利球等)。
六、预加载
创建预加载池,会在 Application OnCreate 中启动异步线程,加载需要被预加载的资源。
1)预创建 Tabview,预加载 Tab 数据,预解析 Tab 数据;
2)预加载类;
3)预加载关注 SDK;
4)预加载主 Fragment;
5)预加载 Delegate;
6)预加载以及预处理缓存以及快照。
七、其他优化
1)直接创建 Delegate,而非通过配置文件配置再反射创建; 2)整合 Delegate,减少向 EventBus 的注册次数; 3)减少字符串拼接操作。
八、快照
由于缓存数据处理是异步的,低端机进入发现后,等待缓存数据处理完成总得有个 Loading 界面,即使提前预加载缓存数据以及预处理好,低端机也不能避免 Loading,为了让用户不再看到过渡页面或者菊花,就得保证主线程能够带着数据渲染,而不是等数据好了后再更新界面。可惜的是,即使缓存反序列后,通过一顿猛如虎的操作:创建 Model、创建 Adapter、卡片布局优化,还是需要 200ms 的时间渲染 3 张卡片。最后,只能通过加载轻量级的缓存数据——快照来完成首屏的展示,加载缓存数据拢共分三步:
1)缓存数据的时候保存一份快照,只保留最简单的一些属性(低质量封图链接,PGC 信息);
2)预加载快照,预创建用于展示快照的容器 view(inflate 或者直接代码实现都可以);
3)进入发现后,优先展示快照,得缓存数据渲染完后,移出快照。
优化后的效果如下:
九、Push 冷启
借助自然冷启的优化成果以及 push 链路的特殊性——以视频起播为目标,特地针对 push
冷启做了以下优化:
1)预加载视频资源;
2)预初始化播放器;
3)去掉 Push 链路不需要的异步任务(缓存以及快照相关的逻辑);
4)调整 Push 链路,以视频起播为最高优先级,改造后的链路如下:
十、总结
启动优化主旨就一个:主线程只做 UI 操作。相伴的手段就是异步预加载,同步懒加载。另外也需要具体场景具体分析,大体步骤就是:通过工具导出启动 Trace 日志,分析整个启动路径的耗时因素,优先解决明显的耗时问题,后续再各个击破。一般情况下,在优化到可接受的目标后即可,而不需要优化到极致,因为性能的优化往往会带来额外的复杂度,比如以上提到的 Push 场景和正常的启动场景就不能复用相同的逻辑。
优化达到目标后需要守护住成果,在日常开发时需要严格守住 UI 线程的底线,上线后需要时常关注性能数据,这样攻防坚守才能持续交付高性能的成果。
作者 | 阿里文娱高级开发工程师 纸贵
评论