2016-09-15 2 views
4

Also habe ich einige Benchmarks auf verschiedenen Datenstrukturen durchgeführt und festgestellt, dass ich 10-20% Performance-Steigerungen hatte, als ich meine Variablen final deklarierte.Java final performance/optimization

Das hat mich wirklich überrascht. Ich dachte, das letzte Schlüsselwort würde nur dazu dienen, die Änderung in Variablen einzuschränken, und die Optimierung würde herausfinden, ob eine Variable einen konstanten Wert hat oder nicht. Hier

ist das Beispiel:

import javafx.scene.input.KeyCode; 
import java.util.*; 

public class Main { 
    static /*final*/ int LOOPS = Integer.MAX_VALUE/100; 

    static /*final*/ KeyCode[] keyCodes = KeyCode.values(); 

    public static void main(String[] args) { 
     long startTime; 
     long endTime; 

     testEnumSet(); //warmup 
     startTime = System.nanoTime(); 
     testEnumSet(); 
     endTime = System.nanoTime(); 
     System.out.println(" EnumSet: " + (endTime - startTime) + "ns"); 
    } 

    static /*final*/ EnumSet<KeyCode> enumSet = EnumSet.noneOf(KeyCode.class); 
    static void testEnumSet() { 
     for (int i = 0; i < LOOPS; i++) { 
      /*final*/ KeyCode add = getRandomKeyCode(); 
      if(!enumSet.contains(add)) enumSet.add(add); 

      /*final*/ KeyCode remove = getRandomKeyCode(); 
      if(enumSet.contains(remove)) enumSet.remove(remove); 
     } 
    } 

    /*final*/ static Random random = new Random(); 
    static KeyCode getRandomKeyCode() { 
     return keyCodes[random.nextInt(keyCodes.length)]; 
    } 
} 

Mit final: .... EnumSet: 652 266 207ns
Ohne Finale: EnumSet: 802 121 596ns

Dies ist konsistent reproduzierbar!

Warum gibt es einen so großen Unterschied zwischen dem Code, der den endgültigen Code verwendet, und dem Code, der nicht verwendet wird? Warum wird es nicht optimiert? Und warum ist Final sowieso schneller, was ist der Unterschied im generierten Bytecode?

+0

[Duplizieren] (http://stackoverflow.com/questions/4279420/does-use-of-final-keyword-in-java-improve-the-performance?rq=1) –

+1

@ JarrodRoberson die am besten bewertete Antwort sagt, es gibt keinen Leistungszuwachs, aber meine Benchmarks zeigen ~ 20% Performancegewinn, also glaube ich nicht, dass dies ein Duplikat ist. – Jhonny007

+0

top bewertet bedeutet nicht immer gemein * richtig * manchmal bedeutet es nur, dass die meisten Menschen falsch liegen. Genauso, wie Ihre Ergebnisse nicht immer reproduzierbar sind und "final" nicht immer messbare Vorteile bietet. –

Antwort

4

Wenn sich etwas niemals ändern kann, können Sie alle möglichen Optimierungen vornehmen, wie zum Beispiel den tatsächlichen Wert eingrenzen, anstatt es immer wieder neu zu suchen. Dies ist nur eine Sache, die Sie tun können, die leicht zu erklären ist und den größten Nutzen bringt.

Es gibt viele andere esoterische Dinge, die passieren, die viel weniger Auswirkungen haben.

Wenn man sich die Bytecode schauen, werden Sie dies sehen, vor allem nach den JIT-Kicks in.

machen die ganze Klasse final ähnliche Vorteile haben kann.

Das heißt, final Referenzen werden Gewinne nicht immer messbar bieten, ist es über die Verwendung des Referenz abhängt. In diesem Fall EnumSet macht eine Menge spezielle Soße Zeug unter der Haube, wenn Sie an der Quelle aussehen. Unveränderliche Referenzen werden wahrscheinlich als Teil von inline eingefügt.

Beachten Sie auch, dass das Verhalten, das Sie in zukünftigen Versionen der JVM könnte weggehen sehen, oder nicht da sein in anderen JVM-Implementierungen. Alles kann sich unter Ihnen ändern, also verlassen Sie sich nicht auf eine bestimmte Implementierung.

Here is some more information in greater detail about all the idiomatic uses of final.

+0

Ja, aber ich dachte, die JVM wäre schlau genug, um zu erkennen, dass eine Variable grundsätzlich endgültig ist, wenn sie nie modifiziert wird (besonders in solch einem einfachen Code) und sie optimieren kann. – Jhonny007

+0

nein es kann nicht die Zukunft vorhersagen, alles, was nicht ausdrücklich von Änderungen begrenzt ist, könnte sich jederzeit in der Zukunft ändern, nur weil es in den letzten 100K Ausführungen nicht geändert hat bedeutet nicht, dass es nicht für die 100.001. –

+0

Aber ist das nicht etwas, das zur Kompilierzeit herausgefunden werden könnte, wenn ein Feld geändert wird? Ich meine, wenn Sie versuchen, ein letztes Feld zu ändern, bemerkt der Compiler Sie und stoppt Sie. – Jhonny007

Verwandte Themen