MusicFree首屏优化记录

在安卓版发布0.6.0之后,有好多小伙伴反馈说首屏太慢了,甚至打开软件要在开屏界面卡10秒,具体时间会随着安装插件的增加而变长。

趁着国庆假期优化了一下,这里记录下问题原因和修复的方案。

问题原因

在软件启动时,会经历一个初始化的阶段。在这个阶段,软件会初始化所有的歌单、播放器内核、插件、主题等等。

在此期间,软件会一直展示一个固定的开屏界面,直到初始化完成。那为啥在 0.6.0 之前,没有感觉到这个问题呢?

因为 0.6.0 之前的版本有 bug,在初始化完成之前就展示了主界面,所以造成了启动很快的错觉,但其实展示主界面之后,软件还在默默地初始化…
而在 0.6.0 版本尝试修复了这个bug,反而看起来像是一个负优化。

所以,0.6.0 版本之前的现象是:软件启动可能要花费 6 秒,但在 2 秒后就展示了主界面,所以大家感觉启动很快;并且大家一般不会在刚打开软件的瞬间就去执行搜索之类的行为,所以大概率也感受不到初始化未完成带来的问题。

而 0.6.0 版本之后的现象是:软件启动可能要花费 6 秒,并且在 6 秒后才展示主界面,实打实等了 6 秒,那感觉就慢下来了。

问题定位

解决首屏问题的思路,无论是前端应用还是跨端应用,个人感觉是类似的 ——

首先找到影响首屏的关键因素,对于首屏必须的数据,能缓存的缓存,能提前获取的提前获取;
对于首屏没那么必要的数据或逻辑,能异步的异步,能延迟的延迟。

在代码里打日志测试了一下初始化每个子步骤所消耗的时间,果然发现插件初始化占了将近一半的时间:

插件初始化的逻辑是:从本地特定的文件夹读取所有已安装的插件,然后解析。这里就有了两个瓶颈:加载 和 解析。

加载指的是读取文件夹和读取文件内容;解析指的是通过 JavaScript 的 new Function 来把插件代码转化成可执行的函数。

如果插件体积比较大、或者经过混淆,就会花费更多的加载和解析时间。

解决方案

按照上面的优化思路,关键因素找到了,是插件初始化。

首屏加载时其实只需要知道插件的接口,或者说,有哪些插件、每个插件的基本信息;
至于每个插件的具体逻辑 (比如获取音源、获取歌词),完全可以等到真正使用到的时候再懒加载。

所以,解决问题的思路就有了:

  1. 缓存已加载插件的所有基础信息(包括插件内定义的属性,方法列表,安装路径);当插件发生变动(添加、删除、更新)时,顺便更新缓存。
  2. 首屏加载时,先读取已安装的所有插件列表(大概20ms),然后根据插件路径读取缓存。
  3. 对于命中缓存的插件,拿到缓存的插件的基础信息,然后跳过加载和解析,直接创建一个未初始化的插件实例,并标记为需要懒加载。
  4. 对于没有命中缓存的插件,还是走原来的初始化流程,读取文件内容并解析,这样就保证了即使手动添加了插件文件,也能正常解析。
  5. 当插件被真正使用(比如调用插件的函数获取音源等)时,或软件空闲时,会初始化需要懒加载的插件,并在初始化完成后更新插件缓存。这样能保证插件的缓存是最新的,并且不会影响功能。

为了防止改出来啥问题,加了一个【启用插件懒加载】的设置项,默认是关闭的。把这个开关打开,就能体验到优化后的效果啦。


莫名想到了之前在淘宝做某互动游戏的时候,首屏加载时间很长,但有个定时更新的假进度条,这样就不会让用户感觉像卡死了,加载久一点也就没那么难熬。这也算是一种优化吧😂