2014-04-24 21 views
5

Nella Scala immutable Vector code c'è un commento che dice:Metodo privato inlining

In linea di principio, la maggior parte dei membri dovrebbero essere privati. Tuttavia, i privilegi di accesso devono essere scelti con cura per non impedire il metodo inline

  1. Qual è l'effetto del privato sulle decisioni inline?
  2. Questo vale anche per Java?

risposta

1

Io non sono un esperto di "decisione del compilatore" ma logicamente direi:

Immaginiamo queste due classi (in Java per esempio):

class A { 

    private B b; 

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

} 

class B { 

    private int number; 

    public void execute { 
    println(number); 
    } 

} 

Se B di execute è inline dal compilatore in a di execute, che porterebbe ad un accesso illegale poiché number è privata in B:

class A { 

    private B b; 

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

} 

Quindi direi che quando ti aspetti qualche "inlining", preferisci evitare l'ambito di alcune variabili non compatibili.

Ovviamente, immagino sia utile in rari casi (soprattutto per l'ottimizzazione delle prestazioni, non immagino altri casi) .. forse il caso che tu lo faccia, altrimenti porterebbe a un sacco di "cattive incapsulazioni". ..

8

Questo generalmente non si applica a Java. I controlli di accesso vengono eseguiti una sola volta durante il processo Resolution. Quando il metodo Java è compilato con JIT, i riferimenti simbolici sono già risolti e verificati. Di fatto, l'inlining non viene eseguito sul bytecode originale, ma sulla rappresentazione intermedia specifica del compilatore. Quindi, i modificatori di accesso di solito non hanno effetti collaterali.

Tuttavia, posso scrivere un banco di prova artificiale di un modificatore private/public influisce notevolmente le prestazioni:

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 

Questo effetto si spiega con un metodo di sintesi access$000 che javac genera a consentire l'accesso a un membro privato della classe interna. Nel caso di test sopra descritto, questo accessorio aggiuntivo impedisce di inlining, poiché il livello massimo predefinito di inlining in HotSpot è 9 (-XX:MaxInlineLevel=9). Poiché getPrivate() non può essere richiamato direttamente dalla classe esterna, il metodo access$000() aggiuntivo esegue il 10 ° livello di chiamata e pertanto non è in linea.