Reputation: 5023
The below is the code which I need to optimize and planned that it would be good to move to the switch construct. But I can compare in case. So I planned to make the comparison (len > 3) as the default case.
If I make the comparison part (len > 3) as the default case and add the default as the first in the switch, will it be faster?
Or how can I make the below code as a switch statement?
if ( len > 3 ) {
// Which will happen more often;
}
else if ( len == 3 ) {
// Next case which may occur often;
} else if ( len == 2 ) {
// The next priority case;
} else {
// And this case occurs rarely;
}
Upvotes: 4
Views: 6706
Reputation: 5336
You can use a range in a case:
switch (len) {
case 3 ... INT_MAX:
// ...
break;
case 2:
// ...
break;
default:
// ...
break;
}
But that is an extension provided by GCC...
Upvotes: 0
Reputation: 2672
You can't move comparisons into a switch statement... it uses single checks for its selections.. i.e.,
switch (len) {
case 1:
// Do case 1 stuff here
break;
case 2:
// Do case 2 stuff here
break;
case 3:
// Do case 3 stuff here
break;
}
Use breaks to prevent the case statements from running into each other. Read more here.
Your code is as 'optimized' as it will get in its current state...
Upvotes: 2
Reputation: 709
If you are worried about speed, the truth is that your if...else
or switch...case
statements won't have a real impact of your application speed unless you have hundreds of them. The places where you lose speed is in your iterations or loops. To answer your question specifically, you cannot convert your if...else
statement to a switch...case
statement with the default
appearing first; but with that said, if you did convert to a switch...case
then you will that they run at the same speed (difference is too minute to be picked up by conventional benchmarking tools).
Upvotes: 1
Reputation: 153899
The only way you're going to know is to benchmark it with your compiler. If performance is an issue, you should use the option to provide the compiler with profiler output, and let it decide; it will generally find the best solution. (Note that even on a specific architecture, like Intel, the best solution in terms of machine instructions may vary from one processor to the next.)
In your case, the switch would probably look like:
switch ( len ) {
case 2:
// ...
break;
case 3:
// ...
break;
default:
if ( len > 3 ) {
// ...
} else {
// ...
}
}
With only two effective cases, the compiler doesn't have much to
work with. A typical implementation (without extreme
optimization) would do bounds checking, then a table lookup for
the two explicit cases. Any decent compiler will then pick up
that the comparison in your default
case corresponds to one of
the bounds checks it has already done, and not duplicate it.
But with only two cases, the jump table will probably not make
a significant difference compared to the two comparisons,
especially as you'll be out of bounds in the most frequent case.
Until you have actual profiler information that this is a bottleneck in your code, I wouldn't worry about it. Once you have that information, you can profile different variants to see which is faster, but I suspect that if you use maximum optimization and feed profiling information back into the compiler, there will be no difference.
Upvotes: 1
Reputation: 18338
Probably not. Both if...else
and switch...case
are high-level constructs. What slows you down is the branch prediction. The better your prediction is the faster your code will run. You should put your most occurring case in first if
, second in the else if
and so on, just like you wrote. For switch
the result depends on the internal compiler implementation which can reorder the cases despite your own order. The default
should be actually reserved for the less occurring situations because rest of the conditions must be checked before falling back to default
.
To conclude all this, performance-wise usage of if...else
is optimal as long as you set your conditions in the correct order. Regarding switch...case
it's compiler specific and depends on the applied optimizations.
Also note that switch...case
is more limited than if...else
since it supports only simple comparison of values.
Upvotes: 6
Reputation: 16582
Although you've accepted what is probably the best answer, I wanted to provide an alternative.
Note that the standard caveat applies - optimisation isn't optimisation unless you've profiled your code.
However if you are encountering poor performance relating to branches, you can reduce or eliminate them. That your code has one or more inequality comparisons is not an obstacle - you can reduce your cases down to a set of direct equalities, and if necessary use that to index a table, rather than branch at all.
void doSomething(int len)
{
static const char* str[] =
{ "%2d > 3\n",
"%2d < 2\n",
"%2d = 2\n",
"%2d = 3\n"
};
int m1 = (len-2)>>31;
int m2 = (len-4)>>31;
int r = (len & m2 & ~m1) + !!m1;
printf(str[r],len);
}
Note that this codes makes several assumptions which may not hold in practice, but as we're making the wild assumption that this even needs optimising in the first place...
Also, note that better optimisations may be possible with more knowledge about the actual range and type of the input parameter, and indeed what the actual actions taken need to be.
Upvotes: 4