JVM如何决定JIT编译方法(将方法归类为"热门")?

Mar*_*ger 30 java jit jvm jvm-hotspot

我已经使用过-XX:+PrintCompilation,我知道JIT编译器的基本技术以及使用JIT编译的原因.

然而,我仍然没有发现JVM如何决定JIT编译方法,即"正确的时间来到JIT编译方法".

我是否正确地假设每个方法都开始被解释,并且只要它不被归类为"热方法"它就不会被编译?我有一些东西在脑后,我读到一个方法被认为是"热",当它执行至少10.000次(解释方法10.000次后,它将被编译),但我不得不承认我是不确定这个或我在哪里读到这个.

总结一下我的问题:

(1)只要没有将每种方法归类为"热"方法(并因此已被编译),或者即使它们不是"热门",也有理由编制方法?

(2)JVM如何将方法分为"非热"和"热"方法?执行次数?还要别的吗?

(3)如果"热"方法存在某些阈值(如执行次数),是否有Java标志(-XX:...)来设置此阈值?

apa*_*gin 55

HotSpot编译策略相当复杂,特别是对于分层编译,它在Java 8中默认启用.它既不是一些执行,也不是CompileThreshold参数问题.

可以在HotSpot源中找到最佳解释(显然,唯一合理的解释),请参阅advancedThresholdPolicy.hpp.

我将总结这个高级编译策略的要点:

  • 执行从第0层(解释器)开始.
  • 编译的主要触发器是
    1. 方法调用计数器i;
    2. 支持柜台b.后向分支通常表示代码中的循环.
  • 每次计数器达到某个频率值(TierXInvokeNotifyFreqLog,TierXBackedgeNotifyFreqLog)时,都会调用编译策略来决定当前运行的方法下一步该做什么.取决于的值i,b而C1和C2的编译器线程的当前负载,可以决定

    • 继续执行口译员;
    • 开始在翻译中剖析;
    • 在第3层使用C1编译方法,并进行进一步重新编译所需的完整配置文件数据;
    • 在第2层使用C1编译方法,没有配置文件,但有可能重新编译(不太可能);
    • 最后在第1层使用C1编译方法,没有配置文件或计数器(也不太可能).

    这里的关键参数是TierXInvocationThresholdTierXBackEdgeThreshold.可以根据编译队列的长度动态调整给定方法的阈值.

  • 编译队列不是FIFO,而是优先级队列.

  • 具有配置文件数据(第3层)的C1编译代码的行为类似,只是切换到下一级别(C2,第4层)的阈值要大得多.例如,在大约200次调用之后,可以在第3层编译解释的方法,而在5000次调用之后,C1编译的方法可以在第4层进行重新编译.

  • 特殊策略用于方法内联.即使它们不"热",也可以将微小的方法内联到调用者中.只有在频繁调用(InlineFrequencyRatio,InlineFrequencyCount)时才能内联更大的方法.

  • 然后有三个小的替代路径.(1)如果C1编译发现方法很简单,则编译为1(C1,无分析),因为4(C2)不会更快.(2)如果C2编译器忙,该方法编译为2(C1,光分析)直到C2不太忙,此时它在3 C1重新编译,完整分析),所以它可以继续到4( C2).(3)如果C1忙,但C2没有,则在解释器中进行分析,因此该方法可以直接进入C2而不通过C1. (6认同)
  • 对我来说,关键的见解是正常路径是0(解释) - > 3(C1,完整分析) - > 4(C2).在那条路径上,C1实际上只存在用于收集C2的配置文件数据. (4认同)
  • @apangin事实证明,10_000次调用的一般知识(包括我的)是错误的.谢谢你的答案. (2认同)

Pet*_*rey 10

控制它的主要参数是 -XX:CompileThreshold=10000

Java 8的Hotspot现在默认使用分层编译,使用从1级到4级的多个编译阶段.我相信1不是优化.级别3是C1(基于客户端客户端),级别4是C2(基于服务器编译器)

这意味着稍微优化可能比您预期的更早发生,并且在达到10K阈值后可以保持很长时间的优化.我见过的最高点是在一百万次调用后消除StringBuilder的转义分析.

注意:循环迭代多次可以触发编译器.例如,10K次的循环就足够了.

1)在方法被认为足够热之前,它被解释.但是,一些JVM(例如Azul Zing)可以在启动时编译方法,您可以强制Hotspot JVM通过内部API编译方法.Java 9也可能有一个AOT(Ahead Of Time)编译器,但它仍在研究AFAIK

2)呼叫次数或迭代次数.

3)是-XX:CompileThreshold=主要的.