2013-02-12 17 views
6

Ich habe einige Tests durchgeführt, um herauszufinden, was die Geschwindigkeitsunterschiede zwischen Getter/Setter und direktem Feldzugriff sind. Ich schrieb eine einfache Benchmark-Anwendung wie folgt aus:Warum erscheint der Methodenzugriff schneller als der Feldzugriff?

public class FieldTest { 

    private int value = 0; 

    public void setValue(int value) { 
     this.value = value; 
    } 

    public int getValue() { 
     return this.value; 
    } 

    public static void doTest(int num) { 
     FieldTest f = new FieldTest(); 

     // test direct field access 
     long start1 = System.nanoTime(); 

     for (int i = 0; i < num; i++) { 
      f.value = f.value + 1; 
     } 
     f.value = 0; 

     long diff1 = System.nanoTime() - start1; 

     // test method field access 
     long start2 = System.nanoTime(); 

     for (int i = 0; i < num; i++) { 
      f.setValue(f.getValue() + 1); 
     } 
     f.setValue(0); 

     long diff2 = System.nanoTime() - start2; 

     // print results 
     System.out.printf("Field Access: %d ns\n", diff1); 
     System.out.printf("Method Access: %d ns\n", diff2); 
     System.out.println(); 
    } 

    public static void main(String[] args) throws InterruptedException { 
     int num = 2147483647; 

     // wait for the VM to warm up 
     Thread.sleep(1000); 

     for (int i = 0; i < 10; i++) { 
      doTest(num); 
     } 
    } 

} 

Jedes Mal, wenn ich es laufen, ich konsistente Ergebnisse wie diese bekommen: http://pastebin.com/hcAtjVCL

Ich frage mich, ob mir jemand erklären könnte, warum Feld Zugang scheint langsamer zu sein als Getter/Setter-Methode Zugriff, und auch, warum die letzten 8 Iterationen unglaublich schnell ausführen.


bearbeiten: Nachdem assylias und Stephen C Kommentare berücksichtigt, ich habe den Code http://pastebin.com/Vzb8hGdc geändert, wo ich etwas andere Ergebnisse erhielt: http://pastebin.com/wxiDdRix.

+2

Ich denke, der Compiler inline die Getter sowieso. Hast du den Bytecode überprüft? – jlordo

+10

'/ * warte auf das Aufwärmen der VM */Thread.sleep (1000);' - so funktioniert es nicht. Die JVM wird nicht warm, wenn es nichts tut ... Ihr Mikro-Benchmark hat mehrere Fehler. Insbesondere: (i) Sie erlauben der JVM nicht wirklich, sich aufzuwärmen. (Ii) Die beiden Pfade, die Sie testen möchten, sind in der gleichen Methode, was einige Optimierungen verhindern könnte. – assylias

+11

@jlordo - das Inlining erfolgt durch den JIT-Compiler. Ich werde in den Bytecodes nicht offensichtlich sein. –

Antwort

9

Die Erklärung ist, dass Ihr Benchmark gebrochen ist.

Die erste Iteration erfolgt mit dem Interpreter.

Field Access: 1528500478 ns 
Method Access: 1521365905 ns 

Die zweite Iteration wird vom Interpreter durchgeführt, mit zu beginnen und wir JIT kompilierten Code zu laufen dann drehen.

Field Access: 1550385619 ns 
Method Access: 47761359 ns 

Die verbleibenden Iterationen werden alle mit JIT-kompiliertem Code ausgeführt.

Field Access: 68 ns 
Method Access: 33 ns 

etcetera 

Der Grund, warum sie sind unglaublich schnell ist, dass der JIT-Compiler die Schleifen entferntoptimiert. Es hat festgestellt, dass sie nichts Nützliches für die Berechnung beigetragen haben. (Es ist nicht klar, warum die erste Zahl scheint durchweg schneller als die zweiten, aber ich bezweifle, dass das optimierte Codefeld im Vergleich zu Verfahren Zugang in sinnvoller Weise misst.)


Re die AKTUALISIERTEN Code/Ergebnisse : Es ist offensichtlich, dass der JIT-Compiler die Schleifen immer noch optimiert.

+0

Also @ Stephen mit Accessoren-Methoden nicht nur für die Verkapselung, es favorisieren auch Geschwindigkeit ?? Das ist schön zu hören!!! – Victor

+0

@Victor - Ich glaube nicht, dass Sie diese Schlussfolgerung ziehen können. In der Tat, ich glaube nicht, dass Sie irgendeine Schlussfolgerung aus diesem Benchmarking ziehen können. Es ist einfach fehlerhaft –

+0

Danke Stephen! Ich verstehe ... ich fing an, das zu denken. Also, wenn Sie Geschwindigkeit suchen, verwenden Sie direkten Zugriff, wenn Sie ein flexibleres Design suchen, verwenden Sie Accessoren Methoden? (Entschuldigung für die offtopic Frage!) – Victor

Verwandte Themen