Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code optimization; switch versus if's

I have a question about whether to use 'case' or 'ifs' in a function that gets called quite a lot. Here's the following as it is now, in 'ifs'; the code is self-explanatory:

int identifyMsg(char* textbuff) {
if (!strcmp(textbuff,"text")) {
    return 1;
}
if (!strcmp(textbuff,"name")) {
    return 2;
}
if (!strcmp(textbuff,"list")) {
    return 3;
}
if (!strcmp(textbuff,"remv")) {
    return 4;
}
if (!strcmp(textbuff,"ipad")) {
    return 5;
}
if (!strcmp(textbuff,"iprm")) {
    return 6;
}
return 0;
}

My question is: Would a switch perform better? I know if using 'ifs', I can place the most likely options at the top.

like image 259
KaiserJohaan Avatar asked Jan 30 '11 12:01

KaiserJohaan


Video Answer


2 Answers

You can't use switch statements for strings because they are pointers and are not evaluted at compile time. You are stuck with using a bunch of if statements.

However for the sake of performance, I believe switches perform better when there are more conditions to check but the difference will be so minute it wouldn't matter.

I've never tested this before though, but I've read about this kind of switch optimization:

switch (value) {
  case frequent_value1:
  case frequent_value2:
  case frequent_value3:
    break;

default:
  switch (value) {
     case infrequent_value1:
     case infrequent_value2:
     case infrequent_value3:
        break;
     }
}
like image 77
Marlon Avatar answered Sep 30 '22 09:09

Marlon


You could use gperf to generate perfect hashes of the "verbs" you want to see. Then you could use a switch statement.

Or, you could do something like this:

switch (textbuff[0])
{
    case 'i':
    {
        switch (textbuff[1])
        {
            case 'p':
            {
                 switch (textbuff[2])
                 {
                     case 'a': /* something. */ break;
                     case 'r': /* something else. */ break;
                 }
            }
        }
    }

(You get the idea).

As yet another option (if all of your commands are 4 characters), turn them into a single 32-bit number and then switch on that:

int32_t mashed =
    textbuff[0] << 24 | 
    textbuff[1] << 16 |
    textbuff[2] << 8 |
    textbuff[3];

switch (mashed) { /* ... */ }

To be honest, though, unless the list of options is particularly large, or this function is being called an obscene number of times, it won't be worth it.

Remember: measure first; optimise later (only if necessary).

like image 26
Roger Lipscombe Avatar answered Sep 30 '22 08:09

Roger Lipscombe