Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a performance difference by excluding an 'Else' clause?

Tags:

c#

.net

Is there a performance difference between the following two pieces of code?

if (myCondition)
{
     return "returnVal1";
}

return "returnVal2"

and

if (myCondition)
{
     return "returnVal1";
}
else
{
     return "returnVal2";
}

My gut feeling is that the compiler should optimize for this and there shouldn't be a difference, but I frequently see it done both ways throughout our code. I'd like to know if it comes down to a matter of preference and readability.

like image 610
The Matt Avatar asked Sep 23 '09 18:09

The Matt


2 Answers

I'm pretty certain the compiler will optimize that out. Do what is most readable/follows convention for you and let the compiler handle simple things like that.

Even if it was not optimized, the performance difference would be pretty negligible.

like image 153
CookieOfFortune Avatar answered Oct 10 '22 10:10

CookieOfFortune


The best way to find out is to look at the code! Here's the code the VS2005 C# produced in release mode:

    static bool F1 (int condition)
    {
      if (condition > 100)
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  mov         dword ptr [ebp-4],ecx 
00000007  cmp         dword ptr ds:[009185C8h],0 
0000000e  je          00000015 
00000010  call        79469149 
00000015  cmp         dword ptr [ebp-4],64h 
00000019  jle         00000024 
      {
        return true;
0000001b  mov         eax,1 
00000020  mov         esp,ebp 
00000022  pop         ebp  
00000023  ret              
      }

      return false;
00000024  xor         eax,eax 
00000026  mov         esp,ebp 
00000028  pop         ebp  
00000029  ret              
            }

    static bool F2 (int condition)
    {
      if (condition > 100)
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  mov         dword ptr [ebp-4],ecx 
00000007  cmp         dword ptr ds:[009185C8h],0 
0000000e  je          00000015 
00000010  call        79469109 
00000015  cmp         dword ptr [ebp-4],64h 
00000019  jle         00000024 
      {
        return true;
0000001b  mov         eax,1 
00000020  mov         esp,ebp 
00000022  pop         ebp  
00000023  ret              
      }
      else
      {
        return false;
00000024  xor         eax,eax 
00000026  mov         esp,ebp 
00000028  pop         ebp  
00000029  ret              
            }

Which shows the two version produce the exact same code, as you would hope for. I also tried a third option:

    static bool F3 (int condition)
    {
      return condition > 100;
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  mov         dword ptr [ebp-4],ecx 
00000007  cmp         dword ptr ds:[009185C8h],0 
0000000e  je          00000015 
00000010  call        794690C9 
00000015  cmp         dword ptr [ebp-4],64h 
00000019  setg        al   
0000001c  movzx       eax,al 
0000001f  mov         esp,ebp 
00000021  pop         ebp  
00000022  ret              
            }

which is far more efficient as it never branches (and branches are usually bad!).

EDIT

Actually, the best way to find out which is more efficient is to profile the code, not look at the assembler.

Also, the code it's produced is quite unusual. The push eax / mov [],ecx bit is the same, surely, as a single push ecx. Also, it passes by register then stores the value on the stack. I wonder if running the code in the debugger to look at the assembler is changing the way the code is generated.

like image 21
Skizz Avatar answered Oct 10 '22 10:10

Skizz