So I was running some benchmarks on different data structures and noticed, that when I declared my variables final I got 10-20% performance increases.
That really surprised me. I thought the final keyword is purely used for restricting change in variables and optimization would figure out if some variable is of constant value or not.
Here is the example:
import javafx.scene.input.KeyCode;
import java.util.*;
public class Main {
static /*final*/ int LOOPS = Integer.MAX_VALUE / 100;
static /*final*/ KeyCode[] keyCodes = KeyCode.values();
public static void main(String[] args) {
long startTime;
long endTime;
testEnumSet(); //warmup
startTime = System.nanoTime();
testEnumSet();
endTime = System.nanoTime();
System.out.println(" EnumSet: " + (endTime - startTime) + "ns");
}
static /*final*/ EnumSet<KeyCode> enumSet = EnumSet.noneOf(KeyCode.class);
static void testEnumSet() {
for (int i = 0; i < LOOPS; i++) {
/*final*/ KeyCode add = getRandomKeyCode();
if(!enumSet.contains(add)) enumSet.add(add);
/*final*/ KeyCode remove = getRandomKeyCode();
if(enumSet.contains(remove)) enumSet.remove(remove);
}
}
/*final*/ static Random random = new Random();
static KeyCode getRandomKeyCode() {
return keyCodes[random.nextInt(keyCodes.length)];
}
}
With final: .... EnumSet: 652 266 207ns
Without final: EnumSet: 802 121 596ns
This is consistently reproducible!
Why is there such an enourmous difference between the code that uses final and the code that doesn't? Why doesn't it get optimized? And why is final faster anyway, what is the difference in the generated bytecode?