Описание производительности :код работает медленнее после прогрева

Приведенный ниже код запускает одно и то же вычисление 3 раза (и не делает многого :, в основном добавляя все числа от 1 до 100m ). Первые 2 блока работают примерно в 10 раз быстрее, чем третий. Я запускал эту тестовую программу более 10 раз, и результаты очень мало отличаются друг от друга.

Во всяком случае, я ожидаю, что третий блок будет работать быстрее (JIT-компиляция ), но типичный вывод:

35974537
36368455
296471550

Может кто-нибудь объяснить, что происходит? (Для ясности: я ничего здесь не исправляю, просто пытаюсь лучше понять, что происходит)

Примечание:

  • ГХ не запускается во время программы (, контролируемой с помощью-XX:+PrintGC)
  • протестировано с версиями Oracle JDK 1.6.0 _30, 1.7.0 _02 и 1.7.0 _05
  • также протестировано со следующими параметрами:-XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m=> тот же результат
  • вместо этого блок помещается в цикл, все прогоны выполняются быстро
  • если блок извлекается в метод, все прогоны выполняются быстро (независимо от того, вызывается ли метод 3 раза или в цикле, не имеет значения)
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;
    }
}
19
задан assylias 20 August 2012 в 13:44
поделиться