HotSpot JIT 内联策略:自顶向下还是自底向上?

15
假设我们有3个方法:从方法1调用方法2,从方法2调用方法3。 方法2和方法3都有30条字节码。另外,为了明确起见,假设方法2总是从方法1恰好调用一次,方法3总是从方法2恰好调用一次。
如果首先内联方法2,则方法3将直接从方法1的主体中调用,并且可以依次内联。如果首先将方法3内联到方法2中,则后者的大小将变为大约60个字节码,并且无法内联,因为默认的MaxInlineSize阈值为35个字节码。
HotSpot JIT inline方法的顺序是自上而下还是自下而上?
2个回答

19
MaxInlineSize 只影响执行次数在一次以上但小于MinInliningThreshold次的方法编译。对于执行次数大于MinInliningThreshold的方法,有不同的设置-XX:FreqInlineSize=…,其默认值更大(与平台相关)。无论如何,热点仍然被内联。您可以通过运行带有-XX:+UnlockDiagnosticVMOptions-XX:+PrintInlining -XX:MaxInlineSize=0的应用程序进行测试。它仍将报告热点的内联(其中包括“(hot)”注释的热点)。只有以前报告为内联的方法才可能获得注释“执行次数< MinInliningThreshold”,然后变成“太大”。如果您降低FreqInlineSize,则可能会收到“热方法太大”的评论。我从未见过使用默认设置时出现这种情况。

现代64位Linux上的FreqInlineSize为325。 - leventov

3

使用以下参数运行代码,可发现两种方法m3首先被内联。我使用了以下jvm参数:-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining。显然,首次执行计数达到内联阈值的方法首先被内联,这在我们的案例中是m3。因此,对于我用于测试的HotSpot,是由上而下执行的,m3首先执行,m2的执行结束。

代码在禁用TieredCompilation、服务器模式的jdk7_u40上运行,操作系统为Windows 8。命令的输出为:

            @ 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字节m2的大小为35字节m3的大小为31字节

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++;
    }
}

原来只有初始方法大小被考虑在内?因为m3之后仍然会内联m2。因此,内联顺序并不重要? - leventov
1
显然它并没有考虑到该方法的字节码大小。我刚刚再次检查了.class文件,确实是这些方法的字节码大小。 - Claudiu
@leventov 如果您查看http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html,您可以看到MaxInlineSize参数的解释。 - Claudiu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接