The code below runs the exact same calculation 3 times (it does not do much: basically adding all numbers from 1 to 100m). The first 2 blocks run approximately 10 times faster than the third one. I have run this test program more than 10 times and the results show very little variance.
If anything, I would expect the third block to run faster (JIT compilation), but the typical output is:
35974537
36368455
296471550
Can somebody explain what is happening? (Just to be clear, I'm not trying to fix anything here, just trying to better understand what is going on)
Note:
- 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;
}
}