2014-04-24 17 views
5

In der Scala immutable Vector code gibt es einen Kommentar, der sagt:Private Methode inlining

Grundsätzlich sind die meisten Mitglieder privat sein sollte. Allerdings müssen die Zugriffsrechte sorgfältig verhindern nicht inlining Methode gewählt werden

  1. Was ist der Effekt von privaten auf inlining Entscheidungen?
  2. Gilt das auch für Java?

Antwort

1

Ich bin kein Experte in "Compiler Entscheidung", aber logisch würde ich sagen:

die diese beiden Klassen Lassen Sie sich vorstellen (in Java zum Beispiel):

class A { 

    private B b; 

    public void execute(){ 
    b.execute(); 
    } 

} 

class B { 

    private int number; 

    public void execute { 
    println(number); 
    } 

} 

Wenn B execute ist inlined vom Compiler in A die execute, wäre es da number zu einem illegalen Zugang führen ist privat in B:

class A { 

    private B b; 

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

} 

Also würde ich sagen, dass wenn Sie etwas "Inlining" erwarten, lieber den Umfang einiger nicht kompatibler Variablen vermeiden.

Natürlich würde ich mir vorstellen, dass es in seltenen Fällen nützlich ist (hauptsächlich zur Leistungsoptimierung, ich kann mir keine anderen Fälle vorstellen) .. vielleicht der Fall, den Sie zeigen, sonst würde es zu vielen "schlechten Verkapselungen" führen. ..

8

Dies gilt in der Regel nicht für Java. Die Zugriffsprüfungen werden nur einmal während des Prozesses Resolution durchgeführt. Wenn die Java-Methode JIT-kompiliert wird, sind die symbolischen Referenzen bereits aufgelöst und verifiziert. Tatsächlich wird das Inlining nicht auf dem ursprünglichen Bytecode ausgeführt, sondern auf der Compiler-spezifischen Zwischendarstellung. Daher haben die Zugriffsmodifizierer normalerweise keine Nebenwirkungen.

Jedoch kann ich einen künstlichen Testfall schreiben, wo ein private/public Modifikator drastisch die Leistung beeinflusst:

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 

Dieser Effekt wird durch ein Syntheseverfahren erklärt access$000 die javac erzeugt zu Erlaube den Zugriff auf ein privates Mitglied der inneren Klasse. Im obigen Testfall verhindert dieser zusätzliche Accessor das Inlining, da der Standard-Höchstwert für das Inlining in HotSpot 9 ist (-XX:MaxInlineLevel=9). Da getPrivate() nicht direkt von der äußeren Klasse aufgerufen werden kann, macht die zusätzliche Methode access$000() die 10. Stufe des Aufrufs und ist daher nicht inline.