不可忘记用爱心接待客旅,因为曾有接待客旅的,不知不觉就接待了天使。---希伯来书13:2
问题描述
chrome应用冷启动缓慢,跟参考机相比在luncher界面点击chrome图标,有一个明显的延迟,然后chrome才被启动起来。从点击图标到第一个界面加载完全显示,问题机相对参考机要慢3s左右。
初步分析
在 Android 平台侧性能优化之应用启动 一文里遇到过假冷启动引发的类似问题,按照这个思路检查排除了假冷启动的可能。
因为chrome都是通过play store跟新到最新版本v58.0.3029.83的。这也排除了chrome版本不同照成的因素。
参考机问题机的硬件参数有差异,问题机硬件是工程机的标准,而参考机是出货的硬件标准。这个可能存在影响,但直觉告诉我不应该有3s这么大的影响。
systrace分析
经过初步分析,该用systrace进一步深入分析。采用命令:
./run_systrace.py -a com.android.chrome gfx input view am app dalvik sched freq idle load -o trace.html
分别抓取参考机和问题机启动chrome的systrace。
问题机启动chrome systrace如下:
参考机启动chrome systrace如下:
注意以上获取的systrace图,高亮的部分bindApplication问题机相对参考机多耗时1s以上,这个是非常不合理的。
放大高亮的bindApplication区域:
通过上图可以看到问题机OpenDexFilesFromOat方法把大部分时间都消耗在了打开base.apk,这个base.apk是未经过oat优化过的chrome apk,而参考机打开的是base.odex。怀疑问题机上系统对chrome未做oat优化。但oat优化是默认开启的啊,怎么在问题机上chrome没有生成对应的odex文件呢?
为了进一步确认问题,我们需要去/data/app/com.android.chrome-1目录下查看到底有没有odex文件生成。坑爹的是user版本没有root权限查看不了,只能去单独烧录一个eng版本的bootimg了。
烧录eng的boot获取root权限查看/data/app/com.android.chrome-1竟然有base.odex,这遇到了什么鬼。。。
再次抓取此时问题机的systrace查看。
可以看到bindApplication由之前的1.888s变成现在的0.848s。已经靠近了参考机bindApplication花费的0.699s,如果再计算上eng boot对性能的影响,此时问题机bindApplication耗时应该很接近参考机了。
问题猜想
只是换了一个boot,不应该出现这种变化。有没有可能通过play store更新的chrome需要重启或者等待一段时间oat优化才会完成呢?因为更新完chrome后马上开始了问题分析,从之前的systrace看确实没有odex文件生成,而烧录eng boot后该odex文件就有了,eng boot应该不会影响odex文件的生成,烧录的过程重启了手机,重启过程很有可能左右该问题的主因。为了验证这个猜想,将参考机问题机的chrome都卸载更新的版本,重新通过play store 更新chrome,抓取systrace做对比参考。
结果发现参考机更新完成后直接测试没有出现OpenDexFilesFromOat耗时过长问题。
在看问题机同样也没有出现OpenDexFilesFromOat耗时过长问题。
卸载新版本,重新更新chrome,没有重启手机竟然没有出现启动异常。难道猜想错了,odex的生成压根与重启手机没有关系?这就有点费解了,跟预期的不一样啊,让人抓狂.
会不会是刚刷完机就复现问题,此时后台任务过多,导致chrome的oat操作没有完成呢?
会不会是JIT的问题呢?
会不会是虽然卸载掉了更新的apk,但某些地方还保留了记录,再次更新后,odex会自动生成呢?
在不成难道这是偶现问题?
满脑子的疑问飞过来,为了解决这些疑问,只有在刷机一次,从新做实验。
刷完机更新完chrome后,为防止偶现问题,多次抓取了冷启动的systrace,都复现问题。
等待30分钟后,再次抓取systrace
看来不是后台任务过多,导致chrome的oat操作没有完成。
多次使用chrome,在抓取systrace分析。同样还是有问题,这里图就不贴了。看来也不是JIT的问题。
在看重启手机后的现象,启动时间终于正常了。
终于找到了问题的表因,原来通过play store更新chrome应用,只有重启系统才会去做odex优化。而如果先卸载掉更新的chrome,在重新更新则没有问题。
刨根溯源
问题原因找到了,那这个问题是play store的问题还是说系统本身的问题,无法完全确认,但猜测很可能是系统本身的问题,google 不会留下这么明显的bug。因此还需要追溯没有做odex的原因。
odex的详细过程这里不展开讲述。后续在单独起一篇做总结。先给出主要的调用关系。
沿着上图最终发现了问题所在。原来之前的同事在做开机优化时做了一个功能,将非重要应用的dex2oat操作放在了开机之后。可是没有考虑好更新应用时的逻辑处理,导致了问题的发生。本质原因找到了,那么该问题解起来就有方向了。这里涉及到具体的功能,不在赘述。
总结
程序员总爱给程序员挖坑,越向底层的改动越要小心,牵一发而动全身啊。
性能问题涉及的模块确实很多,许多问题总是那么的扑朔迷离,一定要有耐心去分析。
通过分析过程,我们也可以看到dex2oat对应用启动的性能确实提升巨大。systrace的好处就是能量化出这种性能差异。