我正在尝试为对延迟敏感的 Java 应用程序编写预热例程,以优化前几个事务,否则这些事务会因动态类加载和 JIT(主要)而变慢。
我面临的问题是,即使我的预热代码加载了所有类并通过多次调用它们(至少 100 次 -XX:CompileThreshold)来练习它们,稍后当实际用户登录这些相同的函数时仍然标记为“非进入者”并再次重新编译,这会导致延迟命中。
JVM flags如下(我只加了-XX:+PrintCompilation -verbose:class tp troubleshoot,其他都是legacy):
-Xms5g -Xmx5g -server -XX:+AggressiveHeap -XX:+UseFastAccessorMethods -XX:+PrintGCDetails -XX:CompileThreshold=100 -XX:-CITime -XX:-PrintGC -XX:-PrintGCTimeStamps -XX:+PrintCompilation -详细:类
#Warmup happens here
12893 2351 my.test.application.hotSpot (355 bytes)
#Real user logs on here
149755 2351 made not entrant my.test.application.hotSpot (355 bytes)
151913 2837 my.test.application.hotSpot (355 bytes)
152079 2351 made zombie my.test.application.hotSpot (355 bytes)
预热后没有类加载发生(我可以看到之前的类加载,所以标志正在工作)。
看起来该函数获得了一个新的 ID(2351 与 2837),这意味着它以某种方式被 JVM 视为“不同的”。
我如何确定 JVM 决定重新编译此函数的原因?
我想这归结为我如何确定 ID 更改的原因?标准是什么?
我尝试将尽可能多的方法和类标记为私有(private),但无济于事。
这是 JRE 1.6.0_45-b06。
感谢任何有关如何排除故障或获取更多信息的提示! :)
最佳答案
对于后人来说,一旦我阅读了热点 JVM 的一些源代码,它就相当简单了。
以下标志将指出导致函数被取消优化和重新编译的确切源代码行:
-XX:+TraceDeoptimization -XX:+WizardMode -XX:+PrintNativeNMethods -XX:+PrintDependencies -XX:+DebugDeoptimization -XX:+LogEvents
通常是这样的 if 语句。
void function (Object object){
if ( object == null ){
// do some uncommon cleanup or initialization
}
do_stuff();
}
假设我的预热代码从未触发 if 语句。
我曾假设整个函数会一次性编译,然而,当 JIT C2 编译器确实决定为该函数生成 native 代码时,它不会为 if 语句生成任何代码,因为该代码路径从未被带走。
它只会在C2编译器线程中生成一个条件分支,生成陷阱和异常处理程序。我认为发生这种情况是因为 native 代码缓存非常小,因此 JVM 编写者不想用可能无用的代码填充它。
无论如何,如果语句为真(即对象永远为空),那么该函数将立即无条件地触发此异常处理并重新编译(导致卡住/延迟按一对顺序命中毫秒)。
当然,我的预热代码不会以与生产完全相同的方式调用每个函数,我敢猜测,在任何复杂的产品中,这几乎是不可能的,而且无论如何都是维护噩梦。
这意味着为了有效地预热 Java 应用程序,代码中的每个 if 语句都需要由预热代码调用。
因此我们将简单地放弃“预热”我们的 Java 代码的想法,因为它并不像某些人认为的那么简单。
出于以下原因,我们将重新编写部分应用程序以支持一次运行数周/数月:
- 更容易维护(我们不需要在预热期间模拟生产并保持更新)
- JIT 不会根据我们的塑料模拟来完成,而是根据生产行为来完成(即,将 JIT 用于它的设计目的,而不是与之抗争)
从长远来看,客户可能会为使用 C/C++ 或类似语言进行重写付费,以获得始终如一的低延迟,但那是以后的事了。
编辑:让我补充一点,更新到更新版本的热点 JVM 或围绕热点 JVM 参数“调整”将永远无法解决此问题。既是雾里看花,又是镜花水月。事实上,热点 JVM 从来没有为可预测的低延迟而编写,而且这个缺点不可能在 Java 用户空间内解决。
关于java - 我如何确定 Hotspot JVM 决定重新编译 JIT :ed code a second time? 的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23403318/