不可忘记用爱心接待客旅,因为曾有接待客旅的,不知不觉就接待了天使。—希伯来书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如下:
Image may be NSFW.
Clik here to view.
参考机启动chrome systrace如下:
Image may be NSFW.
Clik here to view.
注意以上获取的systrace图,高亮的部分bindApplication问题机相对参考机多耗时1s以上,这个是非常不合理的。
放大高亮的bindApplication区域:
Image may be NSFW.
Clik here to view.
通过上图可以看到问题机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查看。
Image may be NSFW.
Clik here to view.
可以看到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的生成压根与重启手机没有关系?这就有点费解了,跟预期的不一样啊,让人抓狂.
Image may be NSFW.
Clik here to view.

会不会是刚刷完机就复现问题,此时后台任务过多,导致chrome的oat操作没有完成呢?
会不会是JIT的问题呢?
会不会是虽然卸载掉了更新的apk,但某些地方还保留了记录,再次更新后,odex会自动生成呢?
在不成难道这是偶现问题?
满脑子的疑问飞过来,为了解决这些疑问,只有在刷机一次,从新做实验。
刷完机更新完chrome后,为防止偶现问题,多次抓取了冷启动的systrace,都复现问题。
Image may be NSFW.
Clik here to view.
等待30分钟后,再次抓取systrace
Image may be NSFW.
Clik here to view.
看来不是后台任务过多,导致chrome的oat操作没有完成。
多次使用chrome,在抓取systrace分析。同样还是有问题,这里图就不贴了。看来也不是JIT的问题。
在看重启手机后的现象,启动时间终于正常了。
Image may be NSFW.
Clik here to view.
终于找到了问题的表因,原来通过play store更新chrome应用,只有重启系统才会去做odex优化。而如果先卸载掉更新的chrome,在重新更新则没有问题。
刨根溯源
问题原因找到了,那这个问题是play store的问题还是说系统本身的问题,无法完全确认,但猜测很可能是系统本身的问题,google 不会留下这么明显的bug。因此还需要追溯没有做odex的原因。
odex的详细过程这里不展开讲述。后续在单独起一篇做总结。先给出主要的调用关系。
Image may be NSFW.
Clik here to view.
沿着上图最终发现了问题所在。原来之前的同事在做开机优化时做了一个功能,将非重要应用的dex2oat操作放在了开机之后。可是没有考虑好更新应用时的逻辑处理,导致了问题的发生。本质原因找到了,那么该问题解起来就有方向了。这里涉及到具体的功能,不在赘述。
总结
程序员总爱给程序员挖坑,越向底层的改动越要小心,牵一发而动全身啊。
性能问题涉及的模块确实很多,许多问题总是那么的扑朔迷离,一定要有耐心去分析。
通过分析过程,我们也可以看到dex2oat对应用启动的性能确实提升巨大。systrace的好处就是能量化出这种性能差异。