Объяснение производительности: код работает медленнее после прогрева
Приведенный ниже код выполняет один и тот же расчет 3 раза (он мало что делает: в основном складываются все числа от 1 до 100 м). Первые 2 блока работают примерно в 10 раз быстрее, чем третий. Я запустил эту тестовую программу более 10 раз, и результаты показывают очень небольшую разницу.
Во всяком случае, я бы ожидал, что третий блок будет работать быстрее (JIT-компиляция), но типичный вывод:
35974537
36368455
296471550
Может кто-нибудь объяснить, что происходит? (Просто чтобы прояснить, я здесь не пытаюсь что-то исправить, просто пытаюсь лучше понять, что происходит)
Замечания:
no GC is run during the program (monitored with-XX:+PrintGC
)
tested with Oracle JDK versions 1.6.0_30, 1.7.0_02 and 1.7.0_05
also tested with the following parameters: -XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m
=> same result
it the block is put in a loop instead, all runs are fast
if the block is extracted to a method, all runs are fast (whether the method is called 3 times or in a loop makes no difference)
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;
}
}