"Use switch instead of if-else, its more readable and has better performance." I have to admit that this was one of my favorite code review comment. Until one fine day, while hacking Apache Sanselan's image format decoding function, I tried optimizing the code based on the same comments and while benchmark there was hardly any difference. I thought about investigating it further. Though found some interesting mail chains, though about posting my finding.
To begin with decided to run some samples on switch and if-else constructs and analyze further.
Wrote three function
1. For if-else - a if-else ladder based on int comparisons
2. For Switch - switch with 21 cases, from 1 to 20
3. For Switch - switch with sparse random values
The reason for choosing two functions for switch was this statement from VM spec "Compilation of switch statements uses the tableswitch and lookupswitch instructions"
Lets see the function codes
if-else
view sourceprint
public static void testIfElse(int jumpLabel) {
if(1 == jumpLabel) {
System.out.println("1");
} else if(2 == jumpLabel) {
System.out.println("2");
} else if(3 == jumpLabel) {
System.out.println("3");
} else if(4 == jumpLabel) {
System.out.println("4");
}
// Removed for simplicity
else {
System.out.println("default");
}
}
Lets see the switch functions
Finite switch version
view sourceprint?
public static void testSwitchFinite(int jumpLable) {
switch (jumpLable) {
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
case 3:
System.out.println("3");
break;
case 4:
System.out.println("4");
break;
case 5:
System.out.println("5");
break;
// Removed other cases for simplicity
default:
System.out.println("default");
break;
}
}
Sparse switch version
view sourceprint?
public static void testSwitchSparse(int jumpLable) {
switch (jumpLable) {
case 100:
System.out.println("1");
break;
case -1:
System.out.println("2");
break;
case 5000:
System.out.println("3");
break;
case -8:
System.out.println("4");
break;
case 1600:
System.out.println("5");
break;
case 250:
System.out.println("250");
break;
// Removed other cases for simplicity
default:
System.out.println("default");
break;
}
}
With the groundwork done, its the benchmarking time. The benchmarking strategy was simple. Run these functions in loop and see the result, with iteration ranging from 100 to 1000.
Lets look at one of the functions
view sourceprint?
public static void testSwitchPerf(int iteration) {
long t1 = System.nanoTime();
for (int i = 0; i < iteration; i++) {
testSwitchFinite(i);
}
long t2 = System.nanoTime();
System.out.println("Time Taken (switch) = "+(t2 - t1)/1000000);
}
Well this was the ground work, after executing the conditions, here is the data
Iteration -> 100 1000
if-else 8 ms 69 ms
switch finite 3 ms 34 ms
switch sparse 7 ms 21 ms
NOTE: There is some difference due to the way data is provided and the sample space doesn't provide precise results. However, since the sample space is same for both, it would serve its purpose
Conclusion
1. There is no significant execution difference between if-else and switch. The difference observed is due to the sample space choosen.
2. If using if-else, its always recommended to put frequently used if condition at the top of if-else ladder
3. The finite switch statement was converted to tableswitch and sparse switch was converted to lookupswitch
would be interested to hear from folks about their experience in relation to this. I would say, i still prefer switch for readability. Henceforth, my review comment shall be modified as "Use switch instead of if-else, its more readable and has better performance