Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

case statement efficiency in c

I have a large switch statement, with about 250 cases, in Visual C:

#define BOP -42
#define COP -823
#define MOP -5759

int getScarFieldValue(int id, int ivIndex, int rayIndex, int scarIndex, int reamIndex)
{
    int returnValue = INT_MAX;  
    switch (id)
    {       
        case BOP      : returnValue  = Scar[ivIndex][rayIndex].bop[scarIndex][reamIndex];    break;
        case COP        : returnValue  = Scar[ivIndex][rayIndex].cop[scarIndex][reamIndex];       break;
        case MOP         : returnValue  = Scar[ivIndex][rayIndex].mop[scarIndex][reamIndex];     break;
        .....
        default:  return(INT_MAX);
     }
}

The #defines, you will notice, have a huge range, from -1 to -10,000. The thing is dog slow, and I'm wondering if spending several hours redefining these 250 defines to a narrower (or even consecutive) range could speed things up. I always thought the compiler would treat the case values in a way that made their numeric value irrelevant, but I have not been able to find any discussion to validate/invalidate that assumption.

like image 770
PaeneInsula Avatar asked Jul 10 '13 06:07

PaeneInsula


People also ask

Is a case statement more efficient than if?

The first of which is that in most cases, case statements are slightly more efficient than a whole bunch of if statements. However the only real reason why case statements are better that will ever really affect you is that they are a lot easier to read.

Which is efficient switch case or if-else?

As it turns out, the switch statement is faster in most cases when compared to if-else , but significantly faster only when the number of conditions is large. The primary difference in performance between the two is that the incremental cost of an additional condition is larger for if-else than it is for switch .

Why are switch statements more efficient?

A switch statement works much faster than an equivalent if-else ladder. It's because the compiler generates a jump table for a switch during compilation. As a result, during execution, instead of checking which case is satisfied, it only decides which case has to be executed.

Why is switch case faster than if-else?

A switch statement is significantly faster than an if-else ladder if there are many nested if-else's involved. This is due to the creation of a jump table for switch during compilation. As a result, instead of checking which case is satisfied throughout execution, it just decides which case must be completed.


2 Answers

Disassemble the compiled code and see what the compiler does. I've looked at the output from several different compilers and large switch statements were always compiled into binary decision trees or jump tables. Jump tables are the most optimal thing you can get and they are more likely to be generated by the compiler if the values you're switching on are in a narrow range. It also helps have a default statement on some compilers (but not necessary on others).

This is one situation where disassembling is your only good option, the details of code generation on this level are rarely well documented.

like image 58
Art Avatar answered Sep 28 '22 11:09

Art


Simple solution: Break switch case into multiple parts.

if(id<=50)
{
    switch(id)
    {
      //All cases between 0 to 50
    }
}
else if (id>50 && id<=100)
{
    switch(id)
    {
      //All cases between 51 to 100
}
//and so on

the choice of range is yours. And dont create many ranges. This will ensure a code faster than your current code. Alternatively you can use function pointers and write functions containing the statements that are to be executed in the case. I would have preferred this method.

typedef struct
{
    void(*Cur_FunctnPtr)();     
}CMDS_Functn;

void (*Cur_Func)();
CMDS_Functn FunctionArray[66] = {
                    /*00-07*/    (*Func1),(*Func2),(*Func3),...
                    /*08-0F*/       

                    /*40-47*/       };

void my_func()
{
...  //what ever code
    Cur_Func = FunctionArray[id].Cur_FunctnPtr; //Load current Function Pointer
        (*Cur_Func)();
... // what ever code
}
like image 27
madD7 Avatar answered Sep 28 '22 13:09

madD7