2012-11-01 17 views
5

Selbst wenn es nicht sein Hauptzweck ist, habe ich immer gedacht, dass das Schlüsselwort final (in einigen Situationen und VM-Implementierungen) dem JIT helfen könnte.
Es könnte eine urbane Legende sein, aber ich habe mir nie vorgestellt, dass das Setzen eines Feldes final die Leistungen negativ beeinflussen könnte.

Bis ich in einigen Code wie das lief:statisches endgültiges Feld, statisches Feld und Leistungen

private static final int THRESHOLD = 10_000_000; 
    private static int [] myArray = new int [THRESHOLD]; 

    public static void main(String... args) { 
     final long begin = System.currentTimeMillis(); 

     //Playing with myArray 
     int index1,index2; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) 
      myArray[index1] = 42;    //Array initial data 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) { 
              //Filling the array 
      for(index2 = index1 << 1; index2 < THRESHOLD; index2 += index1) 
       myArray[index2] += 32; 
     } 

     long result = 0; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1-=100) 
      result += myArray[index1]; 

     //Stop playing, let's see how long it took 
     System.out.println(result); 
     System.out.println((System.currentTimeMillis())-begin+"ms"); 
    } 


Lassen Sie uns einen Blick auf: private static int [] myArray = new int [THRESHOLD];
Unter W7 64-Bit und auf einer Basis von 10 aufeinanderfolgenden Durchläufen, ich die folgenden Ergebnisse:

  1. THRESHOLD = 10^7, 1.7.0u09 Client VM (Oracle):

    • läuft in ~ 2133ms, wenn myArray nicht endgültig ist.
    • läuft in ~ 2287ms wenn myArray ist endgültig.
    • Die-Server-VM erzeugt ähnliche Zahlen, d. H. 2131ms und 2284ms.

  2. THRESHOLD = 3x10^7, 1.7.0u09 Client VM (Oracle):

    • Läufe in 7647ms ~ wenn myArray nicht endgültig ist.
    • läuft in ~ 8190ms wenn myArray ist endgültig.
    • Die -server-VM produziert ~ 7653ms und ~ 8150ms.

  3. THRESHOLD = 3x10^7, 1.7.0u01 Client VM (Oracle):

    • Läufe in 8166ms ~ wenn myArray nicht endgültig ist.
    • läuft in ~ 9694ms wenn myArray ist endgültig. Das ist mehr als 15% Unterschied!
    • Der -server VM erzeugt einen vernachlässigbaren Unterschied zugunsten der nicht endgültigen Version, etwa 1%.

Bemerkung: Ich benutzte die javac des erzeugten Bytecode von JDK 1.7.0u09 für alle meine Tests. Der erzeugte Bytecode ist für beide Versionen genau gleich, mit Ausnahme der myArray Deklaration, die erwartet wurde.

Warum ist die Version mit static final myArray langsamer als die mit static myArray?


EDIT (Aubin Version meiner Schnipsel verwenden):

Es scheint, dass die Unterschiede zwischen der Version mit final Schlüsselwort und den man ohne nur in der ersten Iteration liegt. Irgendwie ist die Version mit final immer langsamer als sein Gegenstück ohne auf der ersten Iteration, dann haben die nächsten Iterationen ähnliche Zeiten.

Zum Beispiel, mit THRESHOLD = 10^8 und läuft mit 1.7.0u09 Client die erste Berechnung dauert ca. 35s, während die zweite 'nur' 30s dauert.

Offensichtlich führte die VM eine Optimierung durch, war das JIT in Aktion und warum trat es nicht früher (zum Beispiel durch Kompilieren der zweiten Ebene der verschachtelten Schleife, dieser Teil war der Hotspot)?

Beachten Sie, dass meine Bemerkungen mit 1.7.0u01 Client-VM noch gültig sind. Mit dieser Version (und möglicherweise früheren Versionen), läuft der Code mit final myArray langsamer als der ohne dieses Schlüsselwort: 2671ms vs 2331ms auf einer Basis von 200 Iterationen.

+2

Nur 2 Sekunden Laufzeit? Ich glaube nicht, dass das JIT dort wirklich ernsthafte Optimierungen vorgenommen hat. –

+4

10 Läufe sind nicht genug, 1000 wird besser, und der erste Lauf kann nicht berücksichtigt werden – Aubin

+0

@Aubin Es wird eine Weile dauern, ich werde den Beitrag aktualisieren, wenn es vorbei sein wird. – Jerome

Antwort

4

IMHO, sollte die Zeit der System.out.println (Ergebnis) nicht hinzugefügt werden, da I/O sehr Variablen und zeitaufwendig sind.

Ich denke, der Faktor der println() Einfluss ist größer, wirklich größer als der endgültige Einfluss.

Ich schlage vor, den Leistungstest wie folgt zu schreiben:

public class Perf { 
    private static final int THRESHOLD = 10_000_000; 
    private static final int[] myArray = new int[THRESHOLD]; 
    private static /* */ long min = Integer.MAX_VALUE; 
    private static /* */ long max = 0L; 
    private static /* */ long sum = 0L; 

    private static void perf(int iteration) { 
     final long begin = System.currentTimeMillis(); 

     int index1, index2; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) { 
     myArray[ index1 ] = 42; 
     } 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) { 
     for(index2 = index1 << 1; index2 < THRESHOLD; index2 += index1) { 
      myArray[ index2 ] += 32; 
     } 
     } 
     long result = 0; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1 -= 100) { 
     result += myArray[ index1 ]; 
     } 
     if(iteration > 0) { 
     long delta = System.currentTimeMillis() - begin; 
     sum += delta; 
     min = Math.min( min, delta); 
     max = Math.max( max, delta); 
     System.out.println(iteration + ": " + result); 
     } 
    } 

    public static void main(String[] args) { 
     for(int iteration = 0; iteration < 1000; ++iteration) { 
     perf(iteration); 
     } 
     long average = sum/999;// the first is ignored 
     System.out.println("Min : " + min  + " ms"); 
     System.out.println("Average: " + average + " ms"); 
     System.out.println("Max : " + max  + " ms"); 
    } 
} 

Und die Ergebnisse von nur 10 Iterationen sind:

Mit Finale:

Min : 7645 ms 
Average: 7659 ms 
Max : 7926 ms 

Ohne Finale:

Min : 7629 ms 
Average: 7780 ms 
Max : 7957 ms 

Ich schlage vor, dass Leser diesen Test durchführen und ihre Ergebnisse zum Vergleich veröffentlichen.

+0

Das ist eigentlich der Einfluss des Finales, an dem ich interessiert bin. Über println (Ergebnis) habe ich es verwendet, um sicherzustellen, dass das Ergebnis vollständig berechnet wird (wer weiß ...). – Jerome

+0

Ja, das ist, weil Sie es nicht messen müssen – Aubin

+0

@Aubin: off Thema: Was bedeutet "AMUO"? –

Verwandte Themen