JIT不编译大型方法的理由是什么?
我想知道为什么JVM的JIT编译器忽略了编译中的“大型方法”。(除非该标志设置为 false。与此同时,大多数关于Java的JIT编译器的讨论都指出,内联是一种超级优化,因为它允许增加需要编译的指令数量。这种更大的编译上下文允许更好地优化执行的代码。有了这个,我假设一个巨大的方法与一个重内联的方法没有太大区别,应该成为JIT编译的一个很好的目标。我在这里错过了什么?DontCompileHugeMethods
我想知道为什么JVM的JIT编译器忽略了编译中的“大型方法”。(除非该标志设置为 false。与此同时,大多数关于Java的JIT编译器的讨论都指出,内联是一种超级优化,因为它允许增加需要编译的指令数量。这种更大的编译上下文允许更好地优化执行的代码。有了这个,我假设一个巨大的方法与一个重内联的方法没有太大区别,应该成为JIT编译的一个很好的目标。我在这里错过了什么?DontCompileHugeMethods
基本上,编译大型方法的投资回报率很低。
热门代码段通常很短。
即使频繁执行一个巨大的方法,热的部分也不太可能覆盖整个方法。例如,考虑一个大型语句,其中通常只执行几个标签。然而,编译单元是一种方法 - 所以JITted代码的大部分将是一种浪费。switch
case
编译庞大的方法需要花费大量的时间和空间。此外,编译时间不会线性增长。相反,编译几个小方法会更有利可图。
机器代码太长会污染指令缓存。
某些优化可以更好地应用于较小的代码段,例如寄存器分配或循环展开。
如果单个方法大于 8K 字节码,则它似乎无论如何都写得很差。
8k的限制可能只是一个过时的启发式方法。回到[TM]时代,JITing有点昂贵(特别是从响应能力的角度来看)。事实上,大多数有趣的优化(想想常数折叠,良好的寄存器分配等)都是超线性的。因此,您需要格外小心,不要停止整个过程半秒钟来运行优化任务,该任务可能只产生一小部分时间作为性能提升。
尽管如此,我想随着经验的增长,更快的处理器和更好的JIT技术,限制可能会有所提升(甚至可能提高一个数量级),但超线性性能的核心问题仍然存在,极限也将如此。