代码之家  ›  专栏  ›  技术社区  ›  Eugene

JVM非内联方法优化

  •  1
  • Eugene  · 技术社区  · 7 年前

    我基本上知道JVM可以做的一些事情 它包含一个方法,比如 scalar replacement escape analysis lock elision 等(我承认我不知道他们所有)。但是如果一个方法太大而不能内联呢?JVM是否可以对这些方法进行任何优化?我在想 loop unrolling 会是一个。。。

    2 回复  |  直到 7 年前
        1
  •  3
  •   apangin    7 年前

    内联是一种uber优化,它拓宽了许多其他优化的范围:公共子表达式消除、常量传播、标量替换等。 一个非内联方法是一个黑盒-JVM不知道这样的方法是否修改对象字段,抛出异常,注册它破坏的异常等等。

    内联有助于其他优化,但这并不意味着没有内联其他优化就不能工作。JIT编译单元是一个方法,JVM可以将几乎所有的优化应用于其范围内的大型非内联方法。假设您通过在源代码中手动内联所有被调用方创建了一个非常大的方法。因此,无论是手动还是自动进行内联,结果控制流/数据流图都将大致相同,因此JIT将能够处理这两种情况。

    让我用下面的JMH基准来演示这一点。和我一起跑 -prof gc 确保在内联和非内联情况下都没有分配对象。

    @State(Scope.Benchmark)
    public class Inline {
        double x = 111;
        double y = 222;
    
        @Benchmark
        public double inline() {
            return doInline(x, y);
    
        }
    
        @Benchmark
        public double noinline() {
            return dontInline(x, y);
        }
    
        @CompilerControl(CompilerControl.Mode.INLINE)
        private double doInline(double a, double b) {
            return new Vector2D(a, b).norm();
        }
    
        @CompilerControl(CompilerControl.Mode.DONT_INLINE)
        private double dontInline(double a, double b) {
            return new Vector2D(a, b).norm();
        }
    
        static class Vector2D {
            private final double x;
            private final double y;
    
            public Vector2D(double x, double y) {
                this.x = x;
                this.y = y;
            }
    
            public double norm() {
                return Math.sqrt(x * x + y * y);
            }
        }
    }
    

    在HotSpot中进行标量替换的一个明显要求是对象构造函数及其所有被调用的方法都是内联的,但调用方本身不需要内联。

        2
  •  0
  •   Karol Dowbecki    7 年前

    Range check elimination 这将是一个不需要内联的优化示例。看一看 Performance Techniques PerformanceTacticIndex

    推荐文章