If-else vs switch – Which is better?
"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
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
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
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
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"
Share your thoughts
I would be very keen to hear from you all, about your opinions and experience about the topic

looks to me like the switch statement has much better performance. It looks like 20-50+ cycles per evaluation faster.
I would disagree with the more readable part of switch. While yes, in the simplest of cases it is more readable, it becomes significantly less readable as you add to the complexity of the statements within.
I work on a high performance server project at a very very larger computer company and if you told me in a department meeting that there was no difference between 8ms and 3ms you would be laughed out of the room.
Besides that, your example is in Java which is interpreted byte code. Each JVM performs differently depending on the implementation (Sun,IBM,etc) and platform. Throwing that completely aside, your assumptions or conclusions may not hold up for other binary languages like C/C++.
In the end benchmarking can only be done on a per-configuration basis. There are too many variables here to say that using an If-else vs a switch has any other impacts than readability/maintainability, when their side-effects are quiet different and while their semantics are similar their usage is called for in different scenarios and aren’t even completely comparable.
Each job as a different tool to solve it.
Just my $0.02.
Isn’t a factor of 2 or more a significant improvement in performance?
A switch statement over an if-else clause is definately better if the code is being executed millions of times. In the aggregate the performance is noticable. I recently changed code that was under heavy use from if-else clauses to map-based switch statements (e.g. Class -> Function) and saw a nice improvement. The code wasn’t as readable, since the map needed to be created statically, but given the usage patterns it was a worthwhile change.
100% more elapsed time (on average?) for an if-else branch is very significant. But that doesn’t even matter, because you never bother to elaborate on how data is provided, why it makes a difference and then you’re sampling with nanoTime() – known to provide 0 accuracy guarantees.
Do a real benchmark.
.02c
Your benchmark is not very useful: System.out.println is the costly operation in your loop, it looks like you’re measuring randomness. Could you publish standard deviation, and the number of tests you ran at least to provide some sort of idea of the reliability of these measures?
In general, forget about nanooptimization like this. It’s a bad idea.
First, wrote easy to read code. Then, *if needed*, profile it.
My 2 cts.
You should really read some stuff about micro benchmarking first, before diving into it. This is a good start:
http://www.ibm.com/developerworks/java/library/j-jtp02225.html
Bob, indeed it is. However, my view was more towards an average programming environment.
Hmm, more or less, I find switch more readable than if-else. However, the ode becomes ugly, if you putin too much into a case.
Scott, I absolutely agree with you. And If I had been working for you, I would have never said that
You have brought in an excellent view here and I shall explore further on this.
Appreciate your taking time to post a comment.
Thanks
Yup, but the benchmarks are not very accurate
Ben, Thanks for the input. I ran the benchmark only couple of hundreds times. And yes in millions iteration, the performance would really add up a lot.
Think, I have put the function used to get the data and the data has number of iterations as well.
Though your point of nanoseconds is valid.
Will try to go for a better benchmark.
Thanks
Good Idea. We can ignore the Sysout’s as its presents for both the executions.
let me work on it further.
Thanks for the pointers.
Thanks! That’s what I often tell people to avoid this syndrome.
Thanks for the pointer. Will definitely work more on this.
I realize you probably weren’t using real world examples (I hope not, anyway), but even so with these examples I’d say if you have code that looks anything like this then its a good bet your abstraction is on shaky ground to begin with and that optimization is probably the least of your concerns.
The problem is that either of these are too brittle in the face of change. Find a higher abstraction first, then optimize.
Thanks Shaun for the pointer. However, my objective here was very simple to see which is better. Most cases that I encounter, there are typically 5-8 conditions. Well, I just wanted to check that what I understand is really true under what circumstances.
This bench is busted. First, get rid of the writing to console. It’s activity will completely dominate the profile. Secondly, I’d take a look at the byte code. I think you’ll find that sparse switch and if-else get about the same byte code so there should be no difference. The range will be a calculated goto and so the result of the bench will be completely dependent on the ordering of the data.
There is no such thing as a simple microbenchmark.
Regards,
Kirk
I forgot to mention the timings are well within the range that you are measuring randomness. Any benchmark needs to be run for a significant period of time to dampen out the resolution of the clock and the cost of getting that measurement.
First, microbenchmarks are a waste of time.
Second, as Shaun says above, using either switch or if-else especially for more than the most trivial of cases is a very good indicator your code is in poor shape and requires redesigning. There is no “better” in this circumstance. Either way it is a pointer to a failure to apply the many well-known and well-proven techniques of object orientated design.
Why are you doing the benchmarking with System.out.printlns?? This is strongly affecting the results you are getting as this is a really time consuming operation. Maybe try to replace it with any other non-trivial opp (so that the compiler does not optimize your code and skip if-else or switch) or try to subtracts from the result the costs of System.out.println?
BTW: this is a really interesting topic, let me know about what you’ll do next
Thanks Kirk! My simple objective was to evaluate my review comment “Which is better” in general context. Console IO is present for both. So the conditions are similar for both cases.
Well Sysouts are present in both cases and its comparative. Since conditions are same, both emit output to console. So this was fine in my case.
Not sure what’s next, right now hacking Apache Vysper code.
The biggest benefit I tell junior programmers, in support of switch statement, is IDE support. If you add an item to an Enumeration, many IDEs will warn you that it is not being used in your switch statement. So the IDE is helping you ensure that your forking code is correct. With if/else, you have to search through the code and hope you don’t make a mistake.
So to me, this is a readability and maintenance issue.
Since many expects are here. I did try to benchmark in between if/else and switch case before. I agreed on switch case is faster than the if/else case, but normally the test is taking the avarage measurement for both statements to get matched. Last time when i did my test, i found another finding, i was using Bios/DSP and use the ADI provided compiler to benchmark the cycle counts for both statements, i found that, the switch statement is faster than the if/else statement. But, the time to match the first case in switch is the same with the time to match the last case, or the default case of the switch, so, regardless which case i matched in the switch statement, it will take the constant cycle times to run the who switch statement, and the cycle time is increasing if there are more case added in, my finding is, for switch statement, the time spent to match any cases is the same, there has no advantage even the first case is matched. Compare to the if/else statement, the last matching condition always take much than the switch, but if the condition always hit the first or second condition, then the cycle time reduced very much, so normally when using the if/else statement, we will prioritize the most likely happen case on top, this can really speed up the comparison compare to switch case since no matter which case it will be matched, the time taken will be constantly long, and it consume more MIPS when more cases added in. Please verify my finding.
I didn’t see anyone mention the underlying issue when dealing with compiled code – whenever you don’t know for sure what the next statement is going to be (at the machine code level), the compiler will have to insert a few (typically 2-3) NOPs to flush the pipeline. I believe the systems I worked on (Ti DSP processors) used 2-3 NOPs to do this. So, all things being equal, every time you evaluate an if/else you have a few wasted instruction cycles. The switch absorbs the overhead once when it looks up the jump offset in the jump table. So, the real question is at which point does the variable overhead (flushing the pipeline every time you see an if statement) outweigh the slightly higher fixed overhead (computing the jump offset). If your algorithm is on the critical path in a real-time environment, these are definitely important issues.