我想知道JVM的JIT编译器为什么忽略“巨大的方法”而不被编译。(除非将DontCompileHugeMethods
标志设置为false。) 同时,Java JIT编译器的大多数讨论都认为内联是一种超级优化,因为它允许增加可以编译的指令的数量。而这种更大的编译上下文允许更好地优化执行的代码。因此,我认为一个巨大的方法与一个经过高度内联的方法没有太大区别,应该是JIT编译的一个很好的目标。我在这里错过了什么?
我想知道JVM的JIT编译器为什么忽略“巨大的方法”而不被编译。(除非将DontCompileHugeMethods
标志设置为false。) 同时,Java JIT编译器的大多数讨论都认为内联是一种超级优化,因为它允许增加可以编译的指令的数量。而这种更大的编译上下文允许更好地优化执行的代码。因此,我认为一个巨大的方法与一个经过高度内联的方法没有太大区别,应该是JIT编译的一个很好的目标。我在这里错过了什么?
大致上,编译巨大的方法的回报率很低。
热点代码通常很短。
即使经常执行一个巨大的方法,热点部分也不太可能覆盖整个方法。
例如,考虑一个大的switch
语句,只有少数case
标签经常被执行。
然而,编译单元是一个方法,因此JITted代码的更大部分将是浪费的。
编译巨大的方法需要花费大量的时间和空间。此外,编译时间并不呈线性增长。 相比之下,编译几个小方法会更加有利。
过长的机器代码污染指令缓存。
某些优化更适用于较小的代码片段,例如寄存器分配或循环展开。
如果单个方法的字节码大于8K,则该方法似乎编写得不好。
尽管如此,我认为随着经验的积累、更快的处理器和更好的JIT技术,限制可能会有所放宽(甚至可能提高一个数量级),但超线性性能的核心问题仍然存在,因此限制也将存在。