-XX:-TieredCompilation 究竟是做啥的?

Posted

技术标签:

【中文标题】-XX:-TieredCompilation 究竟是做啥的?【英文标题】:What exactly does -XX:-TieredCompilation do?-XX:-TieredCompilation 究竟是做什么的? 【发布时间】:2016-12-07 20:31:46 【问题描述】:

使用java -XX:+PrintFlagsFinal,我找到了TieredCompilation 标志,并在网上阅读了一些相关信息。

然而,我仍然不知道确切将它设置为false 时会发生什么。

我知道编译系统支持5个执行级别,基本上分为解释器、C1和C2:

0 级 - 解释器 1 级 - 完全优化的 C1(无分析) 2 级 - C1 带调用和后端计数器 3 级 - 具有完整分析的 C1(2 级 + MDO) 4 级 - C2

来源:http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/2b2511bd3cc8/src/share/vm/runtime/advancedThresholdPolicy.hpp#l34

两个问题:

(1) 通过设置-XX:-TieredCompilation,是否只是禁用了某些级别?如果是,是哪个?

(2) 是否有一些标志来决定是否禁用 C1 或 C2,或者根本不编译?

【问题讨论】:

【参考方案1】:

-XX:-TieredCompilation 禁用中间编译层 (1、2、3),以便在最大优化级别 (C2) 解释或编译方法。

作为副作用,TieredCompilation 标志还会更改编译器线程数、编译策略和默认代码缓存大小。请注意,禁用TieredCompilation

编译器线程会更少; 将选择简单编译策略(基于方法调用和后端计数器)而不是advanced compilation policy; 默认保留代码缓存大小为5 times smaller。

要禁用 C2 编译器并只保留 C1 而没有额外开销,请设置 -XX:TieredStopAtLevel=1

要禁用所有 JIT 编译器并在解释器中运行所有内容,请使用 -Xint

【讨论】:

谢谢!现在我有点困惑,因为我有不同的答案:现在设置-XX:-TieredCompilation (1.) 禁用 C1 并始终编译到最大值 (C2) 或 (2.) 引导 JVM 启发式地决定哪些编译层根据 CPU 禁用(如@AlBlue 所述)?这也让我很难决定接受哪个作为正确答案:P @MarkusWeninger 我在 AlBlue 的回答下发表了评论。这不是很准确。 谢谢,我刚看到。在第二条评论中,您提到了TierXCompileThreshold-XX:CompilationPolicyChoice=2,这两个我还不知道的新事物,但我会读到它们。 :P 但是第一条评论很好地解释了我的问题。【参考方案2】:

正如您所注意到的,JIT 有不同级别(包括根本不运行 JIT)。

在旧版本的 Java 中,您必须首先选择它们(例如 -Xint-client-server)才能仅使用解释器、仅使用客户端 (C1) 编译器或仅使用服务器 (C2) 编译器。

Java 7 附带的分层编译意味着热点编译器可以在这些步骤之间无缝切换。所以发生的情况是,在运行一定量后,代码会用 C1 编译,然后在运行更多之后,它会用 C2 编译。这是基于方法的,因此当应用程序运行时,很大一部分将仅在解释器下运行(用于冷代码),然后在代码运行很多(热)之后,它将被编译为更高效。运行可以看到不同的关卡

$ java -XX:+PrintFlagsFinal -version | grep CompileThreshold
intx Tier2CompileThreshold                     = 0
intx Tier3CompileThreshold                     = 2000
intx Tier4CompileThreshold                     = 15000
openjdk version "1.8.0_92"
OpenJDK Runtime Environment (Zulu 8.15.0.1-macosx) (build 1.8.0_92-b15)
OpenJDK 64-Bit Server VM (Zulu 8.15.0.1-macosx) (build 25.92-b15, mixed mode)

-XX:-TieredCompilation 本质上是TieredCompilation=false,这意味着不要进行此转换,您必须预先选择是使用客户端编译器还是服务器编译器。 JVM 会根据你的 CPU 启发式地决定应用哪种模式;如果您有多个处理器或 64 位 VM,则它将使用服务器 VM (C2),否则将使用客户端 VM (C1)。

所以-Xint 将只使用解释器(即没有编译器)运行,您可以分别选择带有-client-server 的C1 或C2,以及-XX:-TieredCompilation

【讨论】:

谢谢,-Xint-client-server 是我一直在寻找的标志。 如果您想深入兔子洞,我在speakerdeck.com/alblue/hotspot-under-the-hood 中谈到了编译级别:) 谢谢,我去看看! :) @MarkusWeninger -client-server 标志在现代版本的 JDK 中被忽略。使用-XX:-TieredCompilation-XX:TieredStopAtLevel=1 分别禁用C1 或C2。 TierXCompileThreshold 标志不与分层编译一起使用,除非使用 -XX:CompilationPolicyChoice=2 明确选择 SimpleThresholdPolicy。【参考方案3】:

作为 Java 8 用户,建议禁用 TieredComplilation 以用于浮点生产。

Oracle 不会在 Java8 上修复此问题。 所有带 G1GC 的热点 JVM 8 都有相同的问题。

(Bug1) (Bug2)

【讨论】:

从 Java 9 开始修复了错误。 如何禁用分层编译? -XX:-TieredCompilation 你用浮点数做什么? 这些错误已在 8u192 和 8u201 中修复,因此现在可以在 Java 8 中安全使用

以上是关于-XX:-TieredCompilation 究竟是做啥的?的主要内容,如果未能解决你的问题,请参考以下文章

究竟啥是“特级”?

究竟啥是绑定?

究竟啥是“执着无知”?

究竟什么时候该使用MQ?

MissingSchemaAction.AddWithKey 究竟做了啥?

`-rdynamic` 究竟做了啥,啥时候需要它?