我能否强制JVM本地编译给定的方法?

33
我有一个性能关键的方法,在我的应用程序启动时经常被调用。最终,它会被JIT编译,但在解释器中运行一段时间后才会被编译。
有没有办法告诉JVM,我想从一开始就编译这个方法(而不是通过调整其他内部参数,如-XX:CompileThreshold)?

你能否对该方法运行一个真实的、合成的热身,或者它执行的操作无法伪造? - Matt
1
这种方法用于在启动后立即解析大型配置文件,这就是我想要加速的地方。人为热身在这一点上可能没有什么好处,我想... - Jean-Philippe Pellet
你能否简化一下你的配置呢?将它从XML格式改为更简单的属性格式或其他任何方式,以减少读取所需的代码量?也许可以将配置分成一个尽可能小的“引导”部分,只用于启动,和一个主要部分,可以在后台加载?也许可以并行处理工作,即使代码是解释性的,也可以通过线程获得速度提升? - radai
它正在解析JSON。第一次解析文件需要大约2秒钟的时间。随后的解析只需要不到一秒钟的时间。 - Jean-Philippe Pellet
你尝试过将conf文件转换成*.properties文件来查看是否有所改善吗?读取属性文件的代码量要少得多。 - radai
显示剩余2条评论
2个回答

44
我所知道的唯一方法是使用-Xcomp标志,但通常不建议使用。它会强制立即对所有类和方法进行JIT编译第一次运行时。缺点是您将在初始启动时看到性能下降(由于增加了JIT活动)。此标志的另一个主要限制是,它似乎禁用了JIT通常执行的基于增量分析的优化。在标准混合模式下,JIT编译器可以(并且将)根据收集的分析和运行时信息不断地取消优化和重新编译代码的部分。这使它能够“纠正”省略的边界检查、次优内联等错误优化。 -Xcomp禁用了基于分析的优化,并且根据程序的不同,可能会导致总体性能损失相当大,而仅获得很小或没有真正的启动收益,因此不建议使用。
除了相当严格的-Xcomp和控制JIT在解释模式下编译/优化给定方法执行多少次以收集统计数据的-XX:CompileThreshold之外,还有-Xbatch。这会将JIT编译强制为“前台”,基本上阻止对方法的调用,直到它被编译,而不是像通常那样在后台编译。

您没有说明使用哪个Java版本,但如果Java 7是您的选择,它引入了一种名为“分层编译”的新JIT模型(通过-XX:+TieredCompilation开关激活)。分层编译的作用是允许在第一次使用方法时进行初始的小型编译传递,然后根据收集的分析数据稍后进行额外的较大的编译/优化。听起来应该很有趣。

据说它需要一些额外的调整和参数/配置,但我还没有进一步检查它。


感谢您提供这些选项的清单。可惜它们不能在更细的级别上设置... - Jean-Philippe Pellet
我认为分层编译不会造成太大的损害,因为从长远来看它并不会真正改变任何事情。 - radai
我强烈建议不要使用“-Xcomp”。你的情况可能有所不同,但在我的实际例子中,它的性能比“标准混合模式”差了10到30倍。 - Per Lundberg

2
我不确定它是否会完全预编译代码,但您可以将具有关键方法的类添加到JVM的共享数据转储中。有关更多详细信息,请参见此问题
此外,您考虑过JNI吗?如果您的方法非常CPU密集型,它可能会显着加快速度。

有趣。看起来这只是改善了类加载,没有涉及JIT编译器。或者我错了吗?我想避免使用JNI并在部署所有平台时编译本地代码... - Jean-Philippe Pellet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接