Leistungserklärung: Code wird nach dem Aufwärmen langsamer ausgeführt
Der folgende Code führt genau die gleiche Berechnung dreimal durch (er macht nicht viel: Im Grunde addiert er alle Zahlen von 1 bis 100 m). Die ersten beiden Blöcke verlaufen ungefähr zehnmal schneller als der dritte. Ich habe dieses Testprogramm mehr als 10 Mal ausgeführt und die Ergebnisse zeigen nur sehr geringe Abweichungen.
Wenn überhaupt, würde ich erwarten, dass der dritte Block schneller läuft (JIT-Kompilierung), aber die typische Ausgabe ist:
35974537
36368455
296471550
Kann jemand erklären, was passiert? (Um es klar zu sagen, ich versuche hier nichts zu beheben, sondern nur besser zu verstehen, was los ist.)
Hinweis:
Während des Programms wird kein GC ausgeführt (überwacht mit-XX:+PrintGC
)Getestet mit Oracle JDK-Versionen 1.6.0_30, 1.7.0_02 und 1.7.0_05auch mit folgenden Parametern getestet:-XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m
=> gleiches ErgebnisWenn der Block stattdessen in eine Schleife gelegt wird, sind alle Läufe schnellWenn der Block in eine Methode extrahiert wird, sind alle Läufe schnell (ob die Methode dreimal oder in einer Schleife aufgerufen wird, macht keinen Unterschied).public static void main(String... args) {
//three identical blocks
{
long start = System.nanoTime();
CountByOne c = new CountByOne();
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum += c.getNext();
}
if (sum != c.getSum()) throw new IllegalStateException(); //use sum
long end = System.nanoTime();
System.out.println((end - start));
}
{
long start = System.nanoTime();
CountByOne c = new CountByOne();
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum += c.getNext();
}
if (sum != c.getSum()) throw new IllegalStateException(); //use sum
long end = System.nanoTime();
System.out.println((end - start));
}
{
long start = System.nanoTime();
CountByOne c = new CountByOne();
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum += c.getNext();
}
if (sum != c.getSum()) throw new IllegalStateException(); //use sum
long end = System.nanoTime();
System.out.println((end - start));
}
}
public static class CountByOne {
private int i = 0;
private int sum = 0;
public int getSum() {
return sum;
}
public int getNext() {
i += 1;
sum += i;
return i;
}
}