【问题标题】:HotSpot JIT inlining strategy: top-down or down-topHotSpot JIT内联策略:自上而下或自下而上
【发布时间】:2013-09-15 06:37:35
【问题描述】:

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

如果方法 2 先内联,方法 3 将直接从方法 1 的主体中调用,并且可以依次内联。如果方法3先内联到方法2中,后者的大小会变成60字节码左右,不能内联,因为默认MaxInlineSize阈值是35字节码。

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

【问题讨论】:

    标签: java inline jit jvm-hotspot


    【解决方案1】:

    MaxInlineSize 影响至少执行一次但少于MinInliningThreshold 次的方法的编译。对于执行超过MinInliningThreshold 的方法,有一个不同的设置-XX:FreqInlineSize=… 具有更大的(取决于平台的)默认值。不管MaxInlineSize 是什么,热点仍然是内联的。您可以通过使用-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:MaxInlineSize=0 运行应用程序来测试它。它仍然会报告热点的内联(这些带有注释“(热)”)。只有以前报告为内联注释“已执行 FreqInlineSize,您可能会收到类似“hot method too big”之类的 cmets。我从来没有在默认设置下看到过它们。

    【讨论】:

    • FreqInlineSize 在现代 64 位 Linux 上为 325。
    【解决方案2】:

    使用参数运行下面的代码表明这两个方法 m3 首先是内联的。 我为 jvm 使用了以下参数:-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining。显然,第一个执行计数达到内联阈值的方法首先被内联。在我们的例子中是 m3。因此,对于我用于测试的热点,m3 首先执行,m2 执行结束。

    代码在 jdk7_u40 下运行,禁用了 TieredCompilation,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 bytesm2 的大小为 35 bytesm3 的大小为 31 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++;
        }
    }
    

    【讨论】:

    • 原来只考虑了初始方法大小?因为m2 仍然在m3 之后内联。那么,内联顺序无关紧要吗?
    • 显然不是。它似乎考虑了该方法的字节码大小。我只是仔细检查了 .class 文件,这些确实是方法的字节码大小。
    • @leventov 如果您查看oracle.com/technetwork/java/javase/tech/…,您可以看到 MaxInlineSize 参数的说明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 2013-10-05
    • 2012-04-26
    • 2021-10-30
    • 1970-01-01
    • 2011-06-23
    相关资源
    最近更新 更多