Explicación de rendimiento: el código se ejecuta más lento después del calentamiento
El siguiente código ejecuta exactamente el mismo cálculo 3 veces (no hace mucho: básicamente agrega todos los números de 1 a 100 m). Los primeros 2 bloques corren aproximadamente 10 veces más rápido que el tercero. He ejecutado este programa de prueba más de 10 veces y los resultados muestran muy poca variación.
En todo caso, esperaría que el tercer bloque se ejecute más rápido (compilación JIT), pero la salida típica es:
35974537
36368455
296471550
¿Alguien puede explicar lo que está pasando? (Para ser claro, no estoy tratando de arreglar nada aquí, solo estoy tratando de entender mejor lo que está pasando)
Nota:
No se ejecuta ningún GC durante el programa (monitoreado con-XX:+PrintGC
)probado con Oracle JDK versiones 1.6.0_30, 1.7.0_02 y 1.7.0_05También probado con los siguientes parámetros:-XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m
=> mismo resultadoSi el bloque se pone en un bucle, todas las ejecuciones son rápidas.si el bloque se extrae a un método, todas las ejecuciones son rápidas (ya sea que el método se llame 3 veces o en un bucle no hace ninguna diferencia)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;
}
}