NO

Author Topic: Switch versus if-else  (Read 7899 times)

boral

  • Guest
Switch versus if-else
« on: June 28, 2012, 04:33:02 PM »
In a book I found these statements......
 "A switch with 10 cases would work faster than an equivalent if-else ladder. Also, a switch with 2 cases would work slower than if-else  ladder.Why?"
Will anyone please explain the above statement?

CommonTater

  • Guest
Re: Switch versus if-else
« Reply #1 on: June 28, 2012, 04:55:40 PM »
The book may not be accurate.  Many compilers will optimize these chains into almost the same object code, so it's unlikely there would be any significant difference in performance.

I recently did some tests working with two different ways of allocating memory (C malloc() vs WinAPI HeapAlloc() )... I ended up having to program over a million repetitions of each method to find any measurable difference in performance.  The difference is totally insignificant. 

The lesson learned is to avoid the "premature optimization" trap.  I say a trap because most often you will spend more time optimizing the code than you will save by the optimizations. 

Far and away your better plan is to write code that is easily maintained and gets the job done.  When being really clever, stop and ask yourself: "If I come back to this in 3 years will I still be able to follow it?" ... If you don't get a solid "Yes" back... it would be better to produce slightly less optimal code that you can maintain.
« Last Edit: June 28, 2012, 05:11:48 PM by CommonTater »

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Switch versus if-else
« Reply #2 on: June 28, 2012, 06:32:45 PM »
In a book I found these statements......
 "A switch with 10 cases would work faster than an equivalent if-else ladder. Also, a switch with 2 cases would work slower than if-else  ladder.Why?"
Will anyone please explain the above statement?
Well, as CommonTater already mentioned, this statement isn't quite as accurate, it highly depends on both the compiler implementation for at least the switch construct as well as the statements used in both the switch and if-else.

On simple numeric statements, a clever compiler might generate a lookup table, which can process each selection within the switch construct with the same speed. But then a clever compiler, doing a fair amount of optimization, might end up doing the same thing for a chain of if-else statements and not a "compare and branch" chain down the whole list of different else's, where it would take more time to evaluate the comparison each time...

This is one of those cases where IMHO it pays if someone knows assembly language, knows how a processor can actually execute such higher level instructions and what might be a faster option or not.

And on the other side, it is also true what CommonTater said about maintainability of code. A neatly formatted switch construct might be easier to understand and expand than several pages of chained if-else statements. And with only two options in a switch statement and only a short conditionally executed code block for each, a properly formatted if-else might be easier to understand that the switch statement. Or in some case, it might even be better to use the otherwise dreaded
"x = (<condition> ? a : b )

Ralf

CommonTater

  • Guest
Re: Switch versus if-else
« Reply #3 on: June 28, 2012, 07:55:56 PM »
On simple numeric statements, a clever compiler might generate a lookup table, which can process each selection within the switch construct with the same speed. But then a clever compiler, doing a fair amount of optimization, might end up doing the same thing for a chain of if-else statements and not a "compare and branch" chain down the whole list of different else's, where it would take more time to evaluate the comparison each time...

I suppose the answer, if there is sufficient curiosity, would be to build identical function into both a switch and an if-else chain, then run a couple of million passes through each and time them... It's "premature optimization" but for the learning experience it might be a great exercise.
 
On thing I never do is put actual code in switches or if-else chains.  I use them to call functions only.  This might sound a bit silly to those who are used to the other way, but what I've found is that while it does run faster (although not significantly so) it is just a whole lot easier to maintain...
 
Heres some sample code to show what I mean...
Code: [Select]
LRESULT CALLBACK MsgTosser(HWND Wnd,UINT Msg,WPARAM wParm,LPARAM lParm)
  { switch (Msg)
      { // remote commands
        case RM_READY :
          NetRMReady();
          return 0;
        case RM_STOP :
          NetRMStop();
          return 0;
        case RM_BUSY :
          NetRMBusy((PBYTE) lParm);
          return 0;
        case RM_REMOTE :
          NetRMRemote((PRMREMOTE) lParm);
          return 0;
        case RM_NOREMOTE :
          NetRMNoRemote();
          return 0;
        case RM_KILLREMOTE :
          NetRMKillRemote();
          return 0;
        case RM_TIMESTAMP :
          NetCheckTimes(*((PDWORD) lParm));
          return 0;
        case RM_FILETYPE :
          NetAddFileType((PTCHAR) lParm);
        // button messages
        case WM_COMMAND :     
          switch(LOWORD(wParm))
            { case 100 :            // context menu
                ShowAbout(MainWind);
                return 0;
              case 1000 :
              case 1001 :
              case 1002 :
              case 1003 :
              case 1004 :
              case 1005 :
              case 1006 :
              case 1007 :
              case 1008 :
              case 1009 :
              case 1010 :
              case 1011 :
              case 1012 :
              case 1013 :
              case 1014 :
              case 1015 :
                NetSendButton(LOWORD(wParm) - 1000);
                return 0;
              case IDCANCEL :
                SendMessage(MainWind,WM_CLOSE,0,0);
                return 0;
              default :             // unprocessed
                return DefWindowProc(Wnd,Msg,wParm,lParm); }
        // toolbar notifications
        case WM_NOTIFY :
          switch (((LPNMHDR)lParm)->code)
            { case TBN_GETINFOTIP :
                GetButtonTip((LPNMTBGETINFOTIP) lParm);
                return 0;
              case TTN_NEEDTEXT :
                GetMainTip((LPNMTTDISPINFO) lParm); 
                return 0;
              default :
                return DefWindowProc(Wnd,Msg,wParm,lParm); }
        case WM_TIMER :
          NetQueryUpdate();
          return 0;
        case WM_CTLCOLORSTATIC :
          return SetStaticColors((HDC)wParm,(HWND)lParm);
        case WM_HELP :
          ShowHelp(MainWind);
          return 0;
        case WM_CLOSE :           // shutdown
          SendDatagram(Server.Addr,RM_ENDREMOTE,
                            &RemoteCtrl.Slot,sizeof(SLOT));
          DestroyWindow(MainWind);
          return 0;
        case WM_DESTROY :         // exit
          PostQuitMessage(0);
          return 0;
        default :                 // unprocessed
          return DefWindowProc(Wnd,Msg,wParm,lParm); } }

Note that each switch element simply calls a function.  This is done for 2 primary reasons... first because anyone who's ever tried to troubleshoot a pages long switch statement knows how hard it is to find where it went wrong and second because this modularizes the code making it very easy to change or even replace entire sections of code.
 
 

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Switch versus if-else
« Reply #4 on: June 28, 2012, 08:20:19 PM »
On simple numeric statements, a clever compiler might generate a lookup table, which can process each selection within the switch construct with the same speed. But then a clever compiler, doing a fair amount of optimization, might end up doing the same thing for a chain of if-else statements and not a "compare and branch" chain down the whole list of different else's, where it would take more time to evaluate the comparison each time...

I suppose the answer, if there is sufficient curiosity, would be to build identical function into both a switch and an if-else chain, then run a couple of million passes through each and time them... It's "premature optimization" but for the learning experience it might be a great exercise.
Well, the simplest thing is to not even run it but look at the created assembly code... ;-)
Though not always what looks the fasted in fact is...
Quote
On thing I never do is put actual code in switches or if-else chains.  I use them to call functions only.  This might sound a bit silly to those who are used to the other way, but what I've found is that while it does run faster (although not significantly so) it is just a whole lot easier to maintain...
That might highly depend on the "case" (pun intended  ;D ). If the distinction between the code blocks depending on the switch statements is only covered in a few lines of code, like initializing a handful of variables depending on the condition, I think your approach is rather obfuscating the code and make it harder to maintain.

I don't think that there are "hard" rules on how to structure code, it always depends on the purpose and a specific situation. What might be a preferable solution in one case might turn out a nightmare in another. There is sooooo much more to learning how to program than just hacking in some code.

Ralf

PS: I found this morning also a very nice quote from Donald Knuth:
Quote
People who discover the power and beauty of high-level, abstract ideas often make the mistake of believing that concrete ideas at lower levels are relatively worthless and might as well be forgotten. (…) on the contrary, the best computer scientists are thoroughly grounded in basic concepts of how computers actually work, and indeed that the essence of computer science is an ability to understand many levels of abstraction simultaneously.

Offline Stefan Pendl

  • Global Moderator
  • Member
  • *****
  • Posts: 582
    • Homepage
Re: Switch versus if-else
« Reply #5 on: June 28, 2012, 09:19:25 PM »
PS: I found this morning also a very nice quote from Donald Knuth:
Quote
People who discover the power and beauty of high-level, abstract ideas often make the mistake of believing that concrete ideas at lower levels are relatively worthless and might as well be forgotten. (…) on the contrary, the best computer scientists are thoroughly grounded in basic concepts of how computers actually work, and indeed that the essence of computer science is an ability to understand many levels of abstraction simultaneously.
;) :D ;D 8)

I like the simplicity and use modularization for reusable code, so my switches are mostly mixed.
---
Stefan

Proud member of the UltraDefrag Development Team

CommonTater

  • Guest
Re: Switch versus if-else
« Reply #6 on: June 28, 2012, 10:37:57 PM »
I don't think that there are "hard" rules on how to structure code, it always depends on the purpose and a specific situation. What might be a preferable solution in one case might turn out a nightmare in another. There is sooooo much more to learning how to program than just hacking in some code.

:D Yer preaching to the choir my friend... Every program is different, that's what makes this such an enjoyable challenge.  "Never" might have been a bit too strong... how about "almost never".
 

Quote
PS: I found this morning also a very nice quote from Donald Knuth:
Quote
People who discover the power and beauty of high-level, abstract ideas often make the mistake of believing that concrete ideas at lower levels are relatively worthless and might as well be forgotten. (…) on the contrary, the best computer scientists are thoroughly grounded in basic concepts of how computers actually work, and indeed that the essence of computer science is an ability to understand many levels of abstraction simultaneously.

Nice insight... I like that one.
 

CommonTater

  • Guest
Re: Switch versus if-else
« Reply #7 on: June 28, 2012, 10:46:54 PM »
I like the simplicity and use modularization for reusable code, so my switches are mostly mixed.

You mean like this?
Code: [Select]
send(to, from, count)
register short *to, *from;
register count;
{ register n = (count + 7) / 8;
        switch(count % 8 {
        case 0: do {    *to = *from++;
        case 7:         *to = *from++;
        case 6:         *to = *from++;
        case 5:         *to = *from++;
        case 4:         *to = *from++;
        case 3:         *to = *from++;
        case 2:         *to = *from++;
        case 1:         *to = *from++;
                } while(--n > 0);
        }
}

That's Duff's Device  ... and it's just about the most insane bit of programming I've ever seen.
 

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Switch versus if-else
« Reply #8 on: June 28, 2012, 11:44:14 PM »
Code: [Select]
send(to, from, count)
register short *to, *from;
register count;
{ register n = (count + 7) / 8;
        switch(count % 8 {
        case 0: do {    *to = *from++;
        case 7:         *to = *from++;
        case 6:         *to = *from++;
        case 5:         *to = *from++;
        case 4:         *to = *from++;
        case 3:         *to = *from++;
        case 2:         *to = *from++;
        case 1:         *to = *from++;
                } while(--n > 0);
        }
}

That's Duff's Device  ... and it's just about the most insane bit of programming I've ever seen.
That is a perfect example on how NOT to use a switch statement in your code!  8)

Considering that we are here posting in the "Beginners questions" section, this is likely to highly confuse newbies, at best...  ;)
Would be worth posting in the same blog where I found the "uninitialized variable" issue that I posted earlier today in the chat forum...

Though it is a perfectly valid piece of code, just most C newbies aren't likely to understand what exactly the "beauty" of this piece of code is and why on the other hand it is extremely dangerous example at the same time...

Ralf

CommonTater

  • Guest
Re: Switch versus if-else
« Reply #9 on: June 29, 2012, 01:09:57 AM »
Considering that we are here posting in the "Beginners questions" section, this is likely to highly confuse newbies, at best...  ;)

True... but it's such a good example of how not to write code, I just couldn't resist it.
 
Quote
Would be worth posting in the same blog where I found the "uninitialized variable" issue that I posted earlier today in the chat forum...

By all means... go right ahead.  There are lots of websites that feature it, maybe with some googling you can find a better explanation than WikiPedia has.

 
« Last Edit: June 29, 2012, 01:12:45 AM by CommonTater »

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Switch versus if-else
« Reply #10 on: June 29, 2012, 08:57:05 AM »
Simply and strightforward:
The switch statement builds some helper code to make branches, tipically a jump table, if you have few conditions the use of jump table is time consuming.
On the other hand if-then constructs for many conditions imply the check of the whole if-then-elseif chain wasting time.
The the assertion you read is correct: for few test cases is best to use "if-else" construct, when you have many test cases is best to use the switch.
Last consider that if the condition to evaluate is not a constant you cannot use switch.

Consider also that the C language main feature is the portability of the code implying the use of many different compilers, so while what has been write above is absolutely correct, it's better that you don't rely on the compiler itself, but always use good programming tecniques.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide