Private method inlining

前端 未结 2 622
花落未央
花落未央 2020-12-09 13:47

In the Scala immutable Vector code there is a comment that says:

In principle, most members should be private. However, access privileges must be car

相关标签:
2条回答
  • 2020-12-09 14:33

    I'm not an expert in "compiler decision" but logically I would say:

    Let's imagine these two classes (in Java for instance):

    class A {
    
      private B b;
    
      public void execute(){
        b.execute();
      }
    
    }
    
    class B {
    
      private int number;
    
      public void execute {
        println(number);
      }
    
    }
    

    If B's execute is inlined by the compiler into A's execute, it would lead to an illegal access since number is private in B:

    class A {
    
      private B b;
    
      public void execute(){
        println(number);  //OUPS! number is unreachable directly from A
      }
    
    }
    

    So I would say that when you expect some "inlining", prefer to avoid some uncompatible variable's scope.

    Of course, I would imagine it's useful in rare cases (mostly for performance optimization, I don't imagine other cases)..maybe the case you shew, otherwise it would lead to a lot of "bad encapsulations"...

    0 讨论(0)
  • 2020-12-09 14:44

    This generally does not apply to Java. The access checks are performed only once during the Resolution process. When Java method is JIT-compiled, the symbolic references are already resolved and verified. In fact, the inlining is performed not on the original bytecode, but on the compiler-specific intermediate representation. So, the access modifiers does not usually have performace side-effects.

    However, I can write an artificial test case where a private/public modifier dramatically affects the performance:

    public class Test {
        static final Inner inner = new Inner();
    
        static class Inner {
            int x = 1;
    
            int getX1() { return x; }
            int getX2() { return getX1(); }
            int getX3() { return getX2(); }
            int getX4() { return getX3(); }
            int getX5() { return getX4(); }
            int getX6() { return getX5(); }
            int getX7() { return getX6(); }
            int getX8() { return getX7(); }
            int getX9() { return getX8(); }
    
            private int getPrivate() { return getX9(); }
            public int getPublic() { return getX9(); }
        }
    
        @GenerateMicroBenchmark
        public int inlinePrivate() {
            return inner.getPrivate();
        }
    
        @GenerateMicroBenchmark
        public int inlinePublic() {
            return inner.getPublic();
        }
    }
    

    Benchmark                Mode Thr    Cnt  Sec         Mean   Mean error    Units
    b.Test.inlinePrivate    thrpt   1      3    5   289480,928     2247,656 ops/msec
    b.Test.inlinePublic     thrpt   1      3    5  1157970,245    18473,139 ops/msec
    

    This effect is explained by a synthetic method access$000 which javac generates to allow access to a private member of the inner class. In the above test case this extra accessor prevents from inlining, because the default maximum level of inlining in HotSpot is 9 (-XX:MaxInlineLevel=9). Since getPrivate() cannot be called directly from the outer class, the extra access$000() method makes 10th level of invocation and therefore is not inlined.

    0 讨论(0)
提交回复
热议问题