浅谈JIT与AOT
了解过编写代码的人都清楚,过一个程序要上线,最重要的就是打包->编译->发布的工作。
但实际上,代码的发布其实有两个主流分支
- AOT Ahead-Of-Time 传统的编译方式,在发布方完成整体优化编译,运行方只需要下载对应的可执行文件运行即可。
- JIT Just-In-Time 实时编译,发布方负责打包,在运行放进行实时优化和编译。
传统的静态语言,如C/C++,或者新一代的Go/Rust,都是纯AOT路线的。
而脚本语言,比如 javascript/lua/python/php,大都是jit路线的。
而部分带运行时的语言,典型如Java/C#,较新的Dart,则两种发布方式都有。
所以对于带运行时的语言来说,选择JIT还是AOT,还是要考虑一下场景和TradeOff(权衡代价)的。
代码保密性
JIT的程序发布,由于是用时编译,所以,本质是把代码一起发布出去,才能进行优化的。
所以,从代码保密性,是天生低不少的。
虽然AOT发布的2进制代码也存在被逆向的可能,但对于保留大部分代码结构的JIT还是优秀不少的。
在需要强代码保密性的情况下,AOT发布的方式还是很有优势的。
平台限制
对JIT限制的平台,最典型就是品过iOS 的App Store,是无法正常发布JIT程序的。
因为JIT程序本质是依赖于在运行时动态编译程序,所以理论上,在运行时可以编译(生成)成和审核时完全不同的代码。
所以,在发布特定有限制的平台时,也只能使用AOT的方式进行发布。
快速启动
之前我们说过,JIT是在运行时进行编译的。所以,在启动上,JIT程序非常吃亏。
在长时间运行的服务类(Servce)程序上,这个问题并不明显,如果你的服务是以小时,天,甚至年为单位运行的,那么启动时秒级的启动时间无伤大雅。
但是如果是命令行工具/微服务上,JIT的启动时间和内存占用就显得格外突出了。而较短的时间周期也让JIT的运行时优化没有开展的余地。
所以,从时间生命周期来说,短期的CLI程序或者微服务更适合AOT发布,而长生命周期的服务类程序更适合JIT。
性能
性能这块,其实JIT和AOT各有擅长,这个真的要具体情况具体分析了。
首先,JIT有运行时优化(PGO),同时可以动态根据运行时的硬件状况进行优化,所以理论上,JIT因为有更多的信息,可以比AOT有更深入的优化。
但是,AOT也有优势。JIT因为需要先编译运行再优化,所以具体的编译时间和深入度上都有限制,同时也不能花太久的时间进行编译。所以,真正的大型项目,比如操作系统/浏览器,都是AOT开发的,进入深入的优化和长时间的编译。
反射
JIT除了运行时优化外,最大的优势就是在极强的动态反射上。因为所有的代码和类都是运行时编译的,所以也能很方便的进行动态反射处理。这在复杂业务,以及与其他动态语言做对接时能有极大的开发优势。JIT程序改写为AOT程序最大的影响也是在无法使用动态反射上。
选型建议
在可以同时选择JIT和AOT开发项目里(主要是c#),建议以AOT为主的方式(减少动态反射使用)的方式进行开发,这样在发布时进行裁剪也能简单不少。
具体发布的话,需要强代码保密性或者平台限制的选择AOT,复杂系统需要动态反射支持的使用JIT,其他项目根据生命周期判断,生命周期短的采用AOT,越长的JIT越有优势。