Explicação do Desempenho: o código é executado mais lentamente após o aquecimento
O código abaixo executa exatamente o mesmo cálculo 3 vezes (ele não faz muito: basicamente adicionando todos os números de 1 a 100m). Os dois primeiros blocos são executados aproximadamente 10 vezes mais rápido que o terceiro. Eu executei este programa de teste mais de 10 vezes e os resultados mostram muito pouca variação.
No máximo, eu esperaria que o terceiro bloco fosse executado mais rapidamente (compilação JIT), mas a saída típica é:
35974537
36368455
296471550
Alguém pode explicar o que está acontecendo? (Só para ficar claro, não estou tentando consertar nada aqui, apenas tentando entender melhor o que está acontecendo)
Nota:
nenhum GC é executado durante o programa (monitorado com-XX:+PrintGC
)testado com o Oracle JDK versões 1.6.0_30, 1.7.0_02 e 1.7.0_05também testado com os seguintes parâmetros:-XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m
=> mesmo resultadoo bloco é colocado em um loop, todas as corridas são rápidasse o bloco é extraído para um método, todas as execuções são rápidas (se o método é chamado 3 vezes ou em um loop não faz diferença)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;
}
}