-XX:-分层编译到底有什么作用?

2022-08-31 12:38:14

使用我找到了标志,我在网上读到了一些关于它的信息。java -XX:+PrintFlagsFinalTieredCompilation

但是,我仍然不知道将其设置为 时会发生什么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) 解释或编译方法。

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

  • 编译器线程会更少;
  • 将选择简单编译策略(基于方法调用和后备计数器)而不是高级编译策略;
  • 默认保留代码缓存大小将小 5 倍

要禁用 C2 编译器并仅保留 C1 而不产生额外开销,请设置 。-XX:TieredStopAtLevel=1

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


答案 2

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

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

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)

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

因此,将仅使用解释器(即没有编译器)运行,您可以仅选择C1或C2,并分别使用或-Xint-client-server-XX:-TieredCompilation


推荐