Is using one the switch statement better then using multiple if statements?

Started by
20 comments, last by frob 7 years, 9 months ago

If you are using switch() statements for micro-optimizations, there are other tricks to be aware of also; putting your more-frequently used branches closer to the top of the switch() supposedly helps, though I've never tried it.

I thought this was just an optimisation for Java. I can remember doing it back in the 90s when porting C++ code over to Java because the C++ compiler would optimise it away but the javac compiler wouldn't.

Advertisement

Unless you've provided additional information for C++, it probably doesn't do anything to improve performance. It may for other languages that accept non-integer values or systems using JIT with profile-guided results or hotspot analysis, which Java is pretty good at, but most programs using C++ intentionally prefer the payment up front at compile time rather than a performance stutter on a live system.

If you know in advance one condition will be prevalent and the others rare, it should be pulled out with an if statement before the switch. Note that "rare" should really mean on the order of many thousand to one, when 99.99% of the cases will result in a specific expected outcome. Some compilers and tools provide extensions like that, __builtin_expect() or likely() or similar, but those need truly be almost certain results or they'll actually introduce performance penalties instead of benefits.

Unlike some other languages, in C++, a switch statement is just an integer table of blocks of code. The compiler is free to heavily optimize it. The language standard is very terse on the requirements, just six short clauses, so any optimization that keeps those requirements intact is legal.

Exactly how it gets optimized depends on the compiler and the specifics of the code in question.

Just because the C++ code falls through to another branch does not mean the compiler cannot unroll it for each value. The compiler can unroll each value's flow into its own independent chunk of code if it wants to, or leave them consecutive to run into each other.

When there are only a few values and the commands inside each condition are small, the compiler may implement them as jumps exactly as they appear. The compiler may decide an if/else chain jumping from condition to condition is the most efficient choice for that segment of code.

When there are many condition values and all the values are sequential -- even if they appear in a non-sequential order in the source code -- the compiler may turn them into a jump table. For example, if the range is 0-40 and all of them are used, and if x is the selected value, jump to the table value x condition and run it. If the range is something else, 2130-2190, subtract the lower number and do the same. Jump tables are easy enough.

When values are wide spread and especially if they are not continuous, I've seen compilers build a binary searches of the values. if value>73 jump here; if value>36 jump here; if value>18 jump here; if value>9 jump here, etc, quickly jumping with short forward jumps to find the correct condition in a way that is still friendly to the instruction cache.

And the compiler may take a different approach as well, if the rules inside it say there is an efficient alternative.

That's the benefit of using a compiler in the first place. It does the right thing so you don't need to think about it.

This topic is closed to new replies.

Advertisement