有没有一种方法可以在JVM内部判断一个特定的方法是否已经被JIT编译?

6

在编写微基准测试时,运行时间会根据方法是否被编译而产生很大差异。有没有一种方法可以从程序内部判断特定的方法是否已编译?或者,是否有一种方法可以请求编译某个方法,或者知道如何充分预热它,而不需要任何关于JVM传递标志的额外信息?显然,这并不一定完美(例如,可能存在某些条件导致JVM回退到解释代码),但肯定会有所改善。


你可以通过实证测量方法的执行时间并检查结果的分布来进行评估。当它被编译时,通常会出现跳跃。关于这种方法有一个SO上的问题,但我现在找不到了。显然,这有些突兀。 - assylias
我几乎可以确定答案是“不,绝对不可能的”。 - Louis Wasserman
@assylias - 只有在您确定该方法尚未编译时,才能起作用。否则就没有跳转可找到。此外,强大的变化检测算法很难编写。 - Rex Kerr
2个回答

3
对于Sun / Oracle JVM,您可以使用“-XX:CompileThreshold = 1000”设置。
正如官方文档中所述 - 它定义了:

编译之前的方法调用/分支次数

然后,只需使用该数字来“热身”JVM即可。
您还可以使用-XX:-PrintCompilation-XX:CompileThreshold一起使用,以便在编译方法时在控制台上通知您。

JVM中,“分支”是什么? - Rex Kerr
@RexKerr -- JVM 试图估计方法中花费的时间(因此编译它会有多大优势),主要通过计算入口和向后分支(这将指示循环)来实现。但可能还包括其他因素。 - Hot Licks
好的,这似乎是目前最好的答案,尽管不太令人满意。谢谢! - Rex Kerr

1

我相信你可以打开日志记录,以显示方法何时被JIT编译。但是我不知道有没有办法从Java内部告诉它。

请记住,JIT编译不是事件,而是一个过程--随着更多关于其特性的信息变得可用,一个方法可能会被重新编译多次。

最后,请注意,“热身”在一般情况下是不确定的。虽然您通常可以可靠地“热身”单个方法,但由于许多因素,对于甚至是适度大的应用程序来说,这要困难得多。

(尽管我不知道为什么不能将某种JITC状态的读取能力添加到嵌入式调试工具中。)

补充:在对“代码片段”进行基准测试时要注意的一件事是,做所有循环的最外层方法通常是不可JITC的(取决于JITC的实现方式),因为它永远不会返回,因此无法调用JITC版本。因此,应始终将要进行基准测试的代码的“主体”放在单独的方法中,该方法被重复调用,而不是将循环和要进行基准测试的代码放在同一个方法中。


我确实指定了“微基准测试”。更大的应用程序更难确定。 - Rex Kerr
确实。人们还应该注意垃圾回收,测试用例是否具有真实代码的预期多重分派级别,结果是否被丢弃,因此代码可以被省略等等...即使是微基准测试也不容易做到正确! - Rex Kerr

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