Why the switch statement and not if-else? - if-statement

I've been wondering this for some time now. I'm by far not a hardcore programmer, mainly small Python scripts and I've written a couple molecular dynamics simulations. For the real question: What is the point of the switch statement? Why can't you just use the if-else statement?
Thanks for your answer and if this has been asked before please point me to the link.
EDIT
S.Lott has pointed out that this may be a duplicate of questions If/Else vs. Switch. If you want to close then do so. I'll leave it open for further discussion.

A switch construct is more easily translated into a jump (or branch) table. This can make switch statements much more efficient than if-else when the case labels are close together. The idea is to place a bunch of jump instructions sequentially in memory and then add the value to the program counter. This replaces a sequence of comparison instructions with an add operation.
Below are some extremely simplified psuedo-assembly examples. First, the if-else version:
// C version
if (1 == value)
function1();
else if (2 == value)
function2();
else if (3 == value)
function3();
// assembly version
compare value, 1
jump if zero label1
compare value, 2
jump if zero label2
compare value, 3
jump if zero label3
label1:
call function1
label2:
call function2
label3:
call function3
Next is the switch version:
// C version
switch (value) {
case 1: function1(); break;
case 2: function2(); break;
case 3: function3(); break;
}
// assembly version
add program_counter, value
call function1
call function2
call function3
You can see that the resulting assembly code is much more compact. Note that the value would need to be transformed in some way to handle other values than 1, 2 and 3. However, this should illustrate the concept.

Switch can be optimized by compiler - you will get faster code.
Also I find it to be more elegant when dealing with enumerable types.
To sum up switch statement gives you performance + code elegance :)
Here are some useful links:
speed comparison of switch vs if/else in C#
Feedback-Guided Switch Statement
Optimization (pdf describing switch statement optimization)

I'm ignoring this type of low level optimization as usually unimportant, and probably different from compiler to compiler.
I'd say the main difference is readability. if/else is very flexible, but when you see a switch you know right away that all of the tests are against the same expression.

For expressiveness, the switch/case statement allows you to group multiple cases together, for example:
case 1,2,3: do(this); break;
case 4,5,6: do(that); break;
For performance, compilers can sometimes optimize switch statements into jump tables.

Besides the other mentioned Code readability and optimisation in .NET you also get the ability to switch on enums etc
enum Color { Red, Green, Blue };
Color c = Color.Red;
switch (c) // Switch on the enum
{
// no casting and no need to understand what int value it is
case Color.Red: break;
case Color.Green: break;
case Color.Blue: break;
}

The ability to fall through several cases (intentionally leaving out the break statement) can be useful, and as a few people have already said it's faster as well. Perhaps the most important and least important consideration though, is that it just makes for prettier code than if/else. :)

Switch can be optimized "Better" by some compilers. There are pitfalls with using the switch statement in certain languages. In Java, the switch cannot handle strings and in VB2005 the switch statement will not work with radio buttons.
Switch can be faster and easier to read, If-Then is more generic and will work in more places.

The only time switches can be faster are when your case values are constants, not dynamic or otherwise derived, and when the number of cases is significantly larger than the time to calculate a hash into a lookup table.
Case in point for Javascript, which compiles to assembly for execution on most engines, including Chrome's V8 engine, is that switch statements are 30%-60% slower to execute in the common case: http://jsperf.com/switch-if-else/20

Related

Avoiding Branch Operations in Switch Statements [duplicate]

This question already has answers here:
How does switch compile in Visual C++ and how optimized and fast is it?
(2 answers)
Closed 7 years ago.
Instead of a switch statement running iterating through branch after branch, is there away to make assembly look up a list in an array for a goto statement? Or is this usually optimized in the compiler?
Such an optimization would help immensely for large switch statements with constant values.
Ex:
switch(test) {
case 1:
// Do something
break;
case 2:
// Do something
break;
}
"Optimized":
action_link[] = {action_1, action_2};
goto action_link[test];
action_1:
// Do Something
action_2:
// Do Something
The compiler will make this decision for you, based on your optimisation settings and its heuristics about what might make a good jump table.
In many simple situations, the compiler might decide that a naive test-and-jump chain would be faster or smaller than the equivalent jump table.
That is indeed what you should expect from a decent compiler. In fact, the limitations of the switch statement were based on making it easy to translate to a "jump table" instead of multiple branches. Back at the dawn of time, FORTRAN had the "computed GOTO" for the same reason.

How do jump-tables work?

In the following document, pages 4-5:
http://www.open-std.org/jtc1/sc22/wg21/docs/ESC_Boston_01_304_paper.pdf
typedef int (* jumpfnct)(void * param);
static int CaseError(void * param)
{
return -1;
}
static jumpfnct const jumptable[] =
{
CaseError, CaseError, ...
.
.
.
Case44, CaseError, ...
.
.
.
CaseError, Case255
};
result = index <= 0xFF ? jumptable[index](param) : -1;
it is comparing IF-ELSE vs SWITCH and then introduces this "Jump table". Apparently it is the fastest implementation of the three. What exactly is it? I cannot see how it could work??
The jumptable is a method of mapping some input integer to an action. It stems from the fact that you can use the input integer as the index of an array.
The code sets up an array of pointers to functions. Your input integer is then used to select on of these function-pointers. Generally, it looks like it's going to be a pointer to the function CaseError. However, every now and again, it will be a different function that is being pointed to.
It's designed so that
jumptable[62] = Case62;
jumptable[95] = Case95;
jumptable[35] = Case35;
jumptable[34] = CaseError; /* For example... and so it goes on */
Thus, selecting the right function to call is constant time... with the if-elses and selects, the time taken to select the correct function is dependent on the input integer... assuming the compiler doesn't optimize the select to a jumptable itself... if it's for embedded code, then there's a chance that optimizations of this kind have been disabled... you'd have to check.
Once the correct function-pointer is found, the last line simply calls it:
result = index <= 0xFF ? jumptable[index](param) : -1;
becomes
result = index <= 0xFF /* Check that the index is within
the range of the jump table */
? jumptable[index](param) /* jumptable[index] selects a function
then it gets called with (param) */
: -1; /* If the index is out of range, set result to be -1
Personally, I think a better choice would be to call
CaseError(param) here */
Jumpfnct is a pointer to a function. Jumptable is an array that consists of a number of jumpfncts. The functions can be called just by referencing their position in the array.
For example, jumptable0 will execute the first function, passing along param. jumptable1 will execute the second function, etc.
If you don't know about function pointers, you shouldn't use this trick. They're very handy, in a narrow domain.
It's very fast and space efficient, when what you're doing is switching between a large number of similar function calls. You are adding a function call overhead that a switch statement doesn't necessarily have, so it might not be appropriate in all circumstances. If your code is something like this:
switch(x) {
case 1:
function1();
break;
case 2:
function2();
break;
...
}
A jump table might be a good substitution. If, though, your switch is something like this:
switch(x) {
case 1:
y++;
break;
case 1023:
y--;
break;
...
}
It probably wouldn't be worth doing.
I've used them in a toy FORTH language interpreter, where they were invaluable, but in most cases you're not going to see a speed benefit that makes them worth using. Use them if it makes the logic of your program clearer, not for optimization.
This jumptable returns a pointer-to-function by its index. You define this table in a way that invalid indexes point to the function that returns some invalid code (like -1 in the example) and valid indexes point to the functions you need to call.
Construction
jumptable[index]
returns pointer-to-function and this function gets called
jumptable[index](param)
where param is some custom parameter.
A Jump-Table is an obvious, but rarely used optimization, that for some reason seems to have fallen out of favor.
Briefly, instead of testing a value and exiting out of a switch/case or if-else block to branch to function or code path, you create an array which is filled with the addresses of the functions the program can branch to.
Once completed, this arrangement eliminates the relentless if testing attendant with if-else and switch/case blocks. The code uses the variable that would otherwise be tested with if as a subscript into the function-pointer array, and proceeds directly the the appropriate code - sans ANY if testing. A perfectly efficient branch. The assembly code should literally be a jump.
If you profile code, and find a hot-spot where the program is spending a large % of it's time, look to this kind of optimization to improve performance. A little bit of this can go a long way if it's part of a code's hot-spot.
Thanks for the link. Nice find!
As mentioned in the comment above, whether this solution is more or less effiicent than, for example, a switch statement depends on the amount of work needed to be done for each case.
Writing a regular switch statement for the values you want to process will definitely be a clearer way to see what the code does. So unless either space or speed requirements dictate that a more sophisticated solution, I would suggest that this is not a "better" solution.
Tables of function pointers is however an efficient and good way to solve certain problems. I use function pointers in a table quite regularly to do things like "Benchmark 11 different solutions to a problem", where I have a struct wiht the name of the function and the function, and some parameters perhaps. Then I have one function to time and loop over the code a few million times (or whatever it takes to get a long enough measurement to make sense)

Switch statement with huge number of cases

What happens if the switch has more than 5000 case. What are the drawbacks and how we can replace it with something faster?
Note: I am not expecting to use array to store cases as it's the same.
There's no specific reason to think you'd want anything other than a switch/case statement (and indeed I'd actively expect it to be unhelpful). The compiler should create efficient dispatching code, which might involve some combination of static [sparse] table(s) and direct indexing, binary branching etc.; it's got insights into the static values of the cases and should do an excellent job (retuning it on the fly each time you change the cases, whereas new values that don't fit well with a hand-crafted approach - such as wildly differing values when you'd had a pretty packed array lookup - could require reworking of code or silently cause memory bloat or a performance drop).
People really cared about this kind of thing back when C was trying to win over hard-core assembly programmers... the compilers were held accountable for generating good code. Put another way - if it's not (measurably) broken, don't fix it.
More generally, it's great to be curious about this kind of thing and get people's ideas on alternatives and their performance implications, but if you really care and the performance difference could make a useful difference to your program (especially if profiling suggests it) then always benchmark with your program doing real work.
As food for thought... in case one might be stuck with an old/buggy/inefficient compiler or just love hacking.
Inner work of switch statement consist of two parts. Finding address to jump, and well jumping there. For the first part you need to use a table to find the address. If the number of cases increases, table gets bigger - searching address to jump takes time. This is the point compilers tries to optimize, combining several techniques but one easy approach is to use table directly which depends on case value space.
In a back of the napkin example;
switch (n) {
case 1: foo(); break;
case 2: bar(); break;
case 3: baz(); break;
}
with such piece of code compiler can create an array of jump_addresses and directly get the address by array[n]. Now search just took O(1). But if you had a switch like below:
switch (n) {
case 10: foo(); break;
case 17: bar(); break;
case 23: baz(); break;
// and a lot other
}
compiler needs to generate a table containing case_id, jump_address pairs and code to search through that structure which with worst implementation can take O(n). (Decent compilers optimize the hell out of such scenario when they are fully unleashed by enabling their optimization flags to a degree that when you need to debug such optimized code your brain starts to fry.)
Then question is can you do this all yourself at C level to beat the compiler? and funny thing is while creating tables and searching through them seems easy, jumping to a variable point using goto is not possible in standard C. So there is a chance that if you are not going to use function pointers due to overhead or code structure, you are stuck... well if you are not using GCC. GCC has a non-standard feature called Labels as Values which helps you to get pointers to labels.
To complete the example you can write the second switch statement with "labels as values" feature like this:
const void *cases[] = {&&case_foo, &&case_bar, &&case_baz, ....};
goto *labels[n];
case_foo:
foo();
goto switch_end;
case_bar:
bar();
goto switch_end;
case_baz:
baz();
goto switch_end;
// and a lot other
switch_end:
Of course if you are talking about 5000 cases, it is much better if you write a piece of code to create this code for you - and it is probably only way to maintain such software.
As closing notes; will this improve your daily work? No. Will this improve your skills? Yes and talking from experience, I once found myself improved a security algorithm in a smart card just by optimizing case values. It is a strange world.
Try to use Dictionary class with Delegate values. At least it makes code a little bit more readable.
Big switch statement, generally auto-generated one, may take long time to compile. But I like the idea that compiler optimizes the switch statement.
One way to break apart the switch statement is to use bucketing,
int getIt(int input)
{
int bucket = input%16;
switch(bucket)
{
case 1:
return getItBucket1(input);
case 2:
return getItBucket2(input);
...
...
}
return -1;
}
So in the code above, we broke apart our switch statement into 16 parts. It is easy to change the number of buckets in auto-generated code.
This code has added run-time cost of one layer of indirection or function-call. . But considering the buckets defined in different files, it is faster to compile them in parallel.

How does switch compile in Visual C++ and how optimized and fast is it?

As I found out that I can use only numerical values in C++'s switch statements, I thought that there then must be some deeper difference between it and a bunch of if-else's.
Therefore I asked myself:
(How) does switch differ from if-elseif-elseif in terms of runtime speed, compile time optimization and general compilation? I'm mainly speaking of MSVC here.
A switch is often compiled to a jump-table (one comparison to find out which code to run), or if that is not possible, the compiler may still reorder the comparisons, so as to perform a binary search among the values (log N comparisons). An if-else chain is a linear search (although, I suppose, if all the relevant values are compile-time integral constants, the compiler could in principle perform similar optimizations).
Switch statements are often a common source of compiler optimization. That is, how they are treated depends on the optimization settings you use on your compiler.
The most basic (un-optimized) way of compiling a switch statement is to treat it as a chain of if ... else if ... statements. The common way that compilers optimize a switch is to convert it to a jump table which can look something like:
if (condition1) goto label1;
if (condition2) goto label2;
if (condition3) goto label3;
else goto default;
label1:
<<<code from first `case statement`>>>
goto end;
label2:
<<<code from first `case statement`>>>
goto end;
label3:
<<<code from first `case statement`>>>
goto end;
default:
<<<code from `default` case>>>
goto end;
end:
One reason this method is faster is because the code inside the conditionals is smaller (so there's a smaller instruction cache penalty if the conditional is mis-predicted). Also, the "fall-through" case becomes more trivial to implement (the compiler leaves off the goto end statement).
Compilers can further optimize the jump table by creating an array of pointers (to the locations marked by the labels) and use the value you are switching on as an index into that array. This would eliminate nearly all of the conditionals from the code (except for whatever was needed to validate whether the value you are switching on matches one of your cases or not).
A word of caution: nested jump tables are difficult to generate and some compilers refuse to even try to create one. For that reason, avoid nesting a switch inside another switch if maximally-optimized code is important to you (I'm not 100% sure how MSVC in particular handles nested switches, but the compiler manual should tell you).

How to store goto labels in an array and then jump to them?

I want to declare an array of "jumplabels".
Then I want to jump to a "jumplabel" in this array.
But I have not any idea how to do this.
It should look like the following code:
function()
{
"gotolabel" s[3];
s[0] = s0;
s[1] = s1;
s[2] = s2;
s0:
....
goto s[v];
s1:
....
goto s[v];
s2:
....
goto s[v];
}
Does anyone have a idea how to perform this?
It is possible with GCC feature known as "labels as values".
void *s[3] = {&&s0, &&s1, &&s2};
if (n >= 0 && n <=2)
goto *s[n];
s0:
...
s1:
...
s2:
...
It works only with GCC!
goto needs a compile-time label.
From this example it seems that you are implementing some kind of state machine. Most commonly they are implemented as a switch-case construct:
while (!finished) switch (state) {
case s0:
/* ... */
state = newstate;
break;
/* ... */
}
If you need it to be more dynamic, use an array of function pointers.
There's no direct way to store code addresses to jump to in C.
How about using switch.
#define jump(x) do{ label=x; goto jump_target; }while(0)
int label=START;
jump_target:
switch(label)
{
case START:
/* ... */
case LABEL_A:
/* ... */
}
You can find similar code produced by every stack-less parser / state machine generator.
Such code is not easy to follow so unless it is generated code or your problem is most
easily described by state machine I would recommend not do this.
could you use function pointers instead of goto?
That way you can create an array of functions to call and call the appropriate one.
In plain standard C, this not possible as far as I know. There is however an extension in the GCC compiler, documented here, that makes this possible.
The extension introduces the new operator &&, to take the address of a label, which can then be used with the goto statement.
That's what switch statements are for.
switch (var)
{
case 0:
/* ... */
break;
case 1:
/* ... */
break;
default:
/* ... */
break; /* not necessary here */
}
Note that it's not necessarily translated into a jump table by the compiler.
If you really want to build the jump table yourself, you could use a function pointers array.
You might want to look at setjmp/longjmp.
You can't do it with a goto - the labels have to be identifiers, not variables or constants. I can't see why you would not want to use a switch here - it will likely be just as efficient, if that is what is concerning you.
For a simple answer, instead of forcing compilers to do real stupid stuff, learn good programming practices.
Tokenizer? This looks like what gperf was made for. No really, take a look at it.
Optimizing compilers (including GCC) will compile a switch statement into a jump table (making a switch statement exactly as fast as the thing you're trying to construct) IF the following conditions are met:
Your switch cases (state numbers) start at zero.
Your switch cases are strictly increasing.
You don't skip any integers in your switch cases.
There are enough cases that a jump table is actually faster (a couple dozen compare-and-gotos in the checking-each-case method of dealing with switch statements is actually faster than a jump table.)
This has the advantage of allowing you to write your code in standard C instead of relying on a compiler extension. It will work just as fast in GCC. It will also work just as fast in most optimizing compilers (I know the Intel compiler does it; not sure about Microsoft stuff). And it will work, although slower, on any compiler.