package the.plateisbad;
public class Simple {
public static void main(String[] args) {
final long arg_flops;
double i,x = 0.0d, y = 0.0d;
final long start, end;
if (args.length != 2) {
System.out.println("Usage: the.plateisbad.Simple
return;
}
arg_flops = Long.parseLong(args[0]);
y = Long.parseLong(args[1]);
System.out.println("Thinking really hard for " + arg_flops + " flops...");
start = System.currentTimeMillis();
for (i = 0; i < arg_flops; i++) {
x = i * y;
}
end = System.currentTimeMillis();
System.out.println("We calculated: " + x + " in " +(end-start)+ " ms");
}
}
I've stumbled over the fact, that it runs considerably faster when compiled with the Eclipse ECJ compiler compared to a standard javac.
With ECJ, executed with JDK 1.7:
java -server the.plateisbad.Simple 1000000000 3
Thinking really hard for 1000000000 flops...
We calculated: 2.999999997E9 in 1964 ms
With javac, executed with JDK 1.7:
java -server the.plateisbad.Simple 1000000000 3
Thinking really hard for 1000000000 flops...
We calculated: 2.999999997E9 in 3514 ms
With the new JDK 1.8, there is no noticeable difference between javac and ECJ:
java -server the.plateisbad.Simple 1000000000 3
Thinking really hard for 1000000000 flops...
We calculated: 2.999999997E9 in 3727 ms
but it is always the slowest of the three. The Bytecode tells me that ECJ builds a tail controlled loop which loops while i is < arg_flops:
64: invokestatic #52 // Method java/lang/System.currentTimeMillis:()J
67: lstore 9
69: dconst_0
70: dstore_3
71: goto 84
74: dload_3
75: dload 7
77: dmul
78: dstore 5
80: dload_3
81: dconst_1
82: dadd
83: dstore_3
84: dload_3
85: lload_1
86: l2d
87: dcmpg
88: iflt 74
91: invokestatic #52 // Method java/lang/System.currentTimeMillis:()J
while javac builds a head controlled loop that exits if i >= arg_flops:
67: invokestatic #13 // Method java/lang/System.currentTimeMillis:()J
70: lstore 9
72: dconst_0
73: dstore_3
74: dload_3
75: lload_1
76: l2d
77: dcmpg
78: ifge 94
81: dload_3
82: dload 7
84: dmul
85: dstore 5
87: dload_3
88: dconst_1
89: dadd
90: dstore_3
91: goto 74
94: invokestatic #13 // Method java/lang/System.currentTimeMillis:()J
And ECJ uses StringBuffer while javac uses StringBuilder for the String operations, but since these are not in the loop, that should not make any difference.
Does somebody know what is going on here?
UPDATE: This seems to be an anomaly. SciMark 2.0 shows now significant differences between ECJ and javac and jdk1.7 and jdk1.8 - with 1.8 being slightly faster.