Wydajność Objaśnienie: kod działa wolniej po rozgrzaniu
Poniższy kod wykonuje dokładnie te same obliczenia 3 razy (nie robi zbyt wiele: zasadniczo dodaje wszystkie liczby od 1 do 100 m). Pierwsze 2 bloki działają około 10 razy szybciej niż trzeci. Uruchomiłem ten program testowy ponad 10 razy, a wyniki pokazują bardzo małą wariancję.
Jeśli już, spodziewałbym się, że trzeci blok będzie działał szybciej (kompilacja JIT), ale typowy wynik to:
35974537
36368455
296471550
Czy ktoś może wyjaśnić, co się dzieje? (Żeby było jasne, nie próbuję niczego tu naprawiać, po prostu staram się lepiej zrozumieć, co się dzieje)
Uwaga:
żadne GC nie jest uruchamiane podczas programu (monitorowane za pomocą-XX:+PrintGC
)przetestowany z Oracle JDK w wersji 1.6.0_30, 1.7.0_02 i 1.7.0_05testowano również z następującymi parametrami:-XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m
=> ten sam wynikzamiast tego blok jest wprowadzany w pętlę, wszystkie przebiegi są szybkiejeśli blok zostanie wyodrębniony do metody, wszystkie przebiegi są szybkie (bez względu na to, czy metoda jest wywoływana 3 razy, czy w pętli).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;
}
}