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;
    }
}

questionAnswers(2)

yourAnswerToTheQuestion