52

Android冷启动优化总结(四)——profile分析

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUzMDk1NTgzNw%3D%3D&%3Bmid=2247485851&%3Bidx=1&%3Bsn=18c8256367713e418f08e5001090d16d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

小说明:冷启动在Android端分为两部分:

1. 进程启动 — application相关执行完毕

2. 第一个activity展示 — AdvertActivity进入activity栈,init,create,onCreate,onResume后展示。

这次我们分析并着手尝试优化下第一个部分

先看一下profile的耗时统计 6zAJVjn.png!web

  • 第一阶段:LoadedApk.makeApplication newApplication阶段,排除系统必须处理的流程,咱们自己可控部分又根据业务阶段拆分成3个小阶段

  1. 在这个阶段会执行application的attachBaseContext和Application的构造方法

  2. 因为tinker的热修复机制,可以看到,这个阶段99.99%耗时都是在tinker的初始化和相关热修复准备上

  3. application构造方法里,就YogaUtil.getProcessName() (第二列最后一个方法),获取进程名称,几毫秒是咱们自己的操作。

第二阶段:Activity.Thread.installContentProviders 创建contentProviders阶段,我们在这个阶段可以看到很多的contentProviders

  1. YogaWorkManagerInitializer.onCreate

  2. MobProvider.onCreate

  3. SensorsDataContentProvider.onCreate

  4. huawei.UpdateProvider

  5. YouzanProvider

  6. 等等....

第三阶段:Instrumentation.callApplicationOnCreate applicationOnCreate阶段,这是application的onCreate执行,初始化三方sdk和我们进入app前需要提前准备工作执行的地方

  1. 后面所有页面的生命周期绑定准备工作

  2. 启动器(网络初始化,用户信息缓存初始化,三方sdk初始化 等等)

既然有3个阶段,那我们的优化工作就针对这三个阶段分别优化,各个阶段有各个阶段的优化方式:

第一阶段的相关优化

  1. 都是tinker的初始化,如果要优化,唯一的办法就是移除tinker热修复

  2. tinker因为机制问题,需要再次启动app,才会生效热修复的代码,所以最近多半年热修复使用下来,结合咱们app线上实际情况,修复不够及时的需要解决

  3. 如果移除tinker,就要寻找tinker的替代品,选什么好?

  • 首先我们移除tinker然后看profile的日志:

2QJnAzZ.png!web 我们可以明显看到系统 classLoader后,本应该执行的tinker各种初始化肯定都没有了,只有Application构造方法里的YogaUtil.getProcessName(),第一阶段的耗时直接砍掉99.99%。

  • 我们需要找到tinker的替代品,这个替代品需要满足两点:首先是能及时修复,其次是不能在Application里有重代码。而市面上免费开源的HotFix就3家,腾讯系,阿里系,美团;其中腾讯系都跟tinker差不多,而阿里系的免费开源AndFix已经从16年就停止更新了,最新版的HotFix是收费的;又要及时修复,我们只能看美团的robust。

在经过好几个小时的读文档,读demo,写demo后,最终实现了使用robust,说说使用感受:

  1. 相比于tinker就是简单,接入简单,配置简单,修改简单,拆分包简单,打补丁也简单。

  2. 每次冷启动都要加载对应的补丁包,这种机制带来几个问题,一个是application要加载补丁文件(这个还好就是异步加载补丁,比起tinker要少太多工作了),一个是要像个机制能让对应的补丁文件在对应的包上加载。如果要替换,要考虑清楚这两点,并且服务端补丁包下发接口也需要配合修改。(ps: 关于robust的实现,在另外的文档说明)

第二阶段优化

  1. 因为都是contentProvider,所以我移除contentProvider,考虑是否可以换一种实现方式。

移除YogaWorkManagerInitializer后: bY3Q7zZ.png!web

  • 可以看到,YogaWorkManagerInitializer的onCreate不仅没执行,系统紧跟在其后的attachInfo也没有执行了,看了下源码流程,每一个contentProvider的onCreate执行后,系统都要对应执行一段attachInfo做其它操作,所以干掉一个provider不仅仅是干掉自己方法的耗时,同时连带系统的这部分时间也会跟着节省下来。

  • 移除三方sdk的Provider,这个目前shareSdk的Provider没有找到移除的方式,后续看其他三方的provider是否可以移除,移除后再试下功能。

第三阶段优化

  1. 之前所有的任务是顺序执行,耗时长,有一个版本更改成启动器的方式多线程初始化。

  2. 在多线程初始化的基础上,还能做的就是监听每个线程的执行时间,如果任务时间分配不均匀,可以再通过合并or拆分启动任务的方式,让时间最长的任务链减轻任务量,挪到负担轻的任务链里。

总结

如果这三个阶段都可以按上述方式改动的话,对于application这里,通过profile占比,基本还可以缩小50%-70%左右的启动时间。

拖地先生,从事互联网技术工作,在这里每周两篇文章,聊聊日常的实践和心得。往期推荐:

说说这个公众号

平均响应1000ms到200ms,PHP和Go那家强?

崩溃率从1%到0.02%,iOS稳定性解决之道

七招优化Android包体减少30%

技术产品职业瓶颈?29份腾讯通道材料教你成长

低头赶路,也别忘了抬头看天

加班能解决交付的期望么?

6VZJVze.jpg!web

如果对你有帮助,让大家也看看呗~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK