一、事故现场:明明是 AOT,为什么第一次还是卡
1.1 一份典型的 Bug 报告
Bug #9302现象:战斗通行证活动页,第一次打开必卡 180 ms。第二次开始就顺了。复现:100%测试同学的结论:"首次加载嘛,正常。"
测试同学的结论在绝大多数场景下是对的,但在这一个场景下,它把问题挡在了门外。因为战斗通行证是运营的主战场——每个玩家每天至少进三次,而"第一次"永远发生在他刚看完开场 CG、最兴奋、最愿意掏钱的那一刻。
更诡异的是:这个页面的代码,明明已经被 dex2oat 提前编译成了机器码。它为什么还会慢?
1.2 本文要拆掉的那个错误前提
"AOT = 提前把 dex 翻译成机器码"这句话只说对了一半。它漏掉了整个 AOT 最核心、也最有意思的部分:
AOT 不是「翻译」,它是「带着赌注翻译」。
编译发生在代码运行之前。在那个时刻,编译器面对着一堆它注定无法回答的问题:
- 这个类将来会不会有子类?
- 这个方法将来会不会被覆写?
- 这个接口将来会