背景
洋葱学院主APP是洋葱最主要的流量入口,主APP的性能体验直接会影响到学生的学习体验,进一步会影响用户在洋葱的留存。
从7月开始前端、客户端同学经过了多次沟通,梳理出几个问题:
-
客户端黑盒状态,无法通过数据上分析具体的原因。
-
冷启动的速度人肉可感知的慢
-
通过前端监控发现首页白屏时间 3.5s左右,首屏7s左右
-
低版本设备(Android 4.4-)及以下几乎不可用(ps:我们为偏远地区的小朋友提供了大量的低版本Android设备)
-
前端的兼容性问题在所有线上问题中高居不下,严重影响开发效率
接下来会从前端和客户端的2个方向分开去讲我们在过程中的思考和实践。
挑战
前端
上面已经提到过客户端目前是黑盒状态,口径方面我们先制定了前端4大指标(白屏、首屏、可交互、完成),目标上梳理出当前的现状以及同行业的现状。
- 白屏:0.5s
- 首屏:0.8s
- 可交互:1s
- 完成:2.1s
客户端
要进行优化必然要知道现状在哪里?目标或预期是什么?
客户端通过两种方式定义了初期的第一版目标:
-
通过adb的方式求到一个平均数据(当时冷启动3.4s左右)
-
通过trace文件分析,并拆解出对应的生命周期
结合前端和客户端的数据,大概能得到一个结论,APP启动到首屏展示预计在10s左右,已经影响到学生的学习体验。
解决方案
这里主要以Android为例
根据上图,可以拆分出3个阶段APP冷启动、页面白屏、页面渲染。所以根据这三个阶段,分开讲下我们做了哪些事情
客户端
APP冷启动优化
冷启动的过程为从点击图标到MainActivity阶段执行完成。
不支持在 Docs 外粘贴 block
经过几十个版本的迭代开发后,在冷启动过程中已经积累了若干性能问题,解决这些性能瓶颈是冷启动优化工作的首要目标,这些问题主要包括:
-
Application阶段大量阻塞式的同步任务
-
开屏页业务逻辑不合理
-
同时创建5个Fragment 耗时长
-
webview在最后阶段创建
解决方案也针对以上4项
-
阻塞式非必要的移交给子线程处理
-
重新梳理开屏页的业务逻辑,非必须的逻辑延迟或异步处理
-
启动阶段先创建首页fragment,其他延迟处理
-
使用webview池,并提前初始化
优化完成后Android的冷启动时间从3.2s降到0.9s。
优化后的思考
在App早期阶段,冷启动不会有明显的性能问题。随着迭代功能越来越复杂,启动项和业务越来越多,启动时间逐步延长。当我们和业务侧注意到,这个问题已经变的棘手。所以性能治理也是研发需要关注的核心问题。
我们从以下几个方向来规范冷启动阶段:
-
完善冷启动指标和冷启动监控
-
规范启动项,控制增量
-
解决现有瓶颈
预加载
从统计数据上来看,APP除了冷启动的问题之外,有个很核心的问题就是白屏问题,主要原因来自于用户网络情况不同,以及低端设备的性能问题带来的长时间无响应。针对这个问题,我们使用了一套预加载的策略来完成,主要分为以下几部分:
-
资源预加载
-
html预加载
-
API预加载
具体流程如下,通过子线程按照一定的优先级规则,预加载数据和静态资源到本地缓存,访问页面时如果本地缓存已经下载完成,会直接从本地缓存拿缓存好的内容,如果还没有OK,会复用下载列表中的任务。
这里面有几个关键点:
-
API 预加载数据使用过后,会即可销毁,防止因为缓存带来的bug。
-
HTML预加载的数据,1分钟销毁
前端
通过前端性能监控,看到前端的问题集中在2块
-
资源加载慢
-
首屏渲染慢
落实到纯前端层面,优化手段也会集中在这俩块,总结一下我们使用到的方案
-
CDN。除HTML外所有的资源CDN化,这里提一下我们目前的CDN比较坑,对刷新CDN资源有限制,随意HTML是没有上到CDN
-
缓存。其中使用了PWA的缓存策略,本地数据缓存等等。
-
拆出页面首屏。拆解出那些是首屏使用的内容或是关键内容,按照优先级分批次渲染,加载页面的渲染进度。
-
瘦身。把无用的资源剔除,一些通用的包使用native预加载完成加载。
总结与反思
总体来说成绩是有的,Android 冷启动时间从3.2s下降到0.95s,**用户启动APP等待时间缩短了70%,H5 整体白屏时间从789ms降到了440ms,已经优于上面设定的目标(500ms),**但是对于优化这事任重道远,需要从业务、前端、客户端、后端多方位优化,也要考虑后续如何才能保证持续迭代的过程中不会反弹回去。
我们持续在招聘
我们正在持续招聘优秀的同学,期望你和我们一起构建更加优秀的教育产品。简历可以投递到liuqing_dev@guanghe.tv