热点JIT内联策略:自上而下或自下而下

2022-09-04 01:35:20

假设我们有 3 个方法:从方法 1 调用方法 2,从方法 2 调用方法 3。方法 2 和 3 的大小分别为 30 字节码。此外,假设对于确定性,方法 2 总是从方法 1 调用一次,而方法 3 总是从方法 2 调用一次。

如果首先内联方法 2,则将直接从方法 1 的主体调用方法 3,并且可以依次内联方法 3。如果首先将方法 3 内联到方法 2 中,则后者的大小将变为大约 60 个字节码,并且无法内联,因为默认阈值为 35 个字节代码。MaxInlineSize

HotSpot JIT 内联方法的顺序是:自上而下还是自上而下?


答案 1

会影响至少执行一次但仅少于几次的方法的编译。对于执行次数多于方法的方法,具有不同的设置具有更大的(依赖于平台的)默认值。无论 .您可以通过使用 运行应用程序来测试它。它仍然会报告热点的内联(这些带有注释“(hot)”)。只有以前报告为内联了注释“< MinInliningThreshold时间”的方法才可能使注释“太大”。如果您设置了,您可能会收到诸如“热方法太大”之类的评论。我从未见过它们具有默认设置。MaxInlineSizeMinInliningThresholdMinInliningThreshold-XX:FreqInlineSize=…MaxInlineSize-XX:+UnlockDiagnosticVMOptions-XX:+PrintInlining-XX:MaxInlineSize=0FreqInlineSize


答案 2

使用参数运行以下代码显示,两种方法 m3 都首先内联。我对 jvm 使用了以下参数: .显然,第一个执行计数达到内联阈值的方法首先内联。在我们的例子中,m3。因此,对于我用于测试的热点,我首先执行并执行结束。-XX:+UnlockDiagnosticVMOptions -XX:+PrintInliningm3m2

代码在 windows 8 box 上禁用了分层编译,服务器模式与jdk7_u40一起运行。该命令的输出为:

            @ 66   java.lang.String::indexOfSupplementary (71 bytes)   too big
            @ 21   methodTest::m3 (31 bytes)   inline (hot)
            @ 11   methodTest::m2 (35 bytes)   inline (hot)
              @ 21   methodTest::m3 (31 bytes)   inline (hot)
            @ 14   methodTest::m1 (25 bytes)   inline (hot)
              @ 11   methodTest::m2 (35 bytes)   inline (hot)
                @ 21   methodTest::m3 (31 bytes)   inline (hot)

m1是大小, 是 和 具有 。25 bytesm235 bytesm331 bytes

public class methodTest {

    public static void main(String[] args) {
        doTest();
    }

    int i = 0;
    int j = 0;
    int k = 0;

    private static void doTest() {
        methodTest m = new methodTest();

        for (int i = 0; i < 1000000000; i++) {
            m.m1();
        }
        System.out.println(m.i);
        System.out.println(m.j);
        System.out.println(m.k);
    }

    private void m1() {
        i++;
        m2();
        j++;
    }

    private void m2() {
        i++;
        i++;
        m3();
        j++;
    }

    private void m3() {
        i++;
        j++;
        k++;
    }
}

推荐