Is there a difference in performance excluding the Else clause?

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

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

and

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

I feel that the compiler should optimize for this, and there shouldn't be a difference, but I often see how this is done in our code. I would like to know if it comes to the issue of preference and readability.

+6
c #
source share
8 answers

The best way to find out is to look at the code! Here's the VS2005 C # code created 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 that the two versions produce the exact same code you would hope for. I also tried the 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 much more efficient since it never branches (and branches are usually bad!).

EDIT

In fact, the best way to find out which is more efficient is to profile the code, rather than looking at the assembler.

In addition, the code he generated is rather unusual. The current eax / mov [], ecx is the same, of course, as one push ecx. In addition, it passes the register and then stores the value on the stack. I wonder if the code works in the debugger to look at the assembler by changing the way the code is generated.

+12
source share

I am sure that the compiler optimizes this. Do what most reads / follows the convention for you, and let the compiler handle such simple things.

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

+13
source share

While optimization is a good thing, readability plays an important role, so if you think it helps readability better than the nanosecond you save. IMHO

+5
source share

If your compiler does not optimize it for the same bytecode, throw it out of the window!

+4
source share

I would be very surprised if there was a performance hit, and the code suggests that this did not happen.

After many years of trying to figure out outdated code in which several coders tried to optimize expressions in an editor and produced surprisingly impenetrable code, I can only say that you have to write what makes sense and expresses what you want in the simplest and most understandable way.

All code fragments are easy to understand because they are small, but imagine that the logic spans multiple pages ...

+2
source share

You can discover this for yourself by creating a test project with these two options. Then open the project in ildsam or Reflector to see the disassembly. You will know exactly what happens next.

+1
source share

As for the question, it will not have a performance problem if the case when you always evaluate is an else clause.

As stated in the comments, you should just return myCondition. However, you should always include the else clause for readability. If else does nothing, then specify it with the classic comment:

 //do nothing 

It helps developers look at the code after it is written to understand that the else case has been considered, but there is no situation where it exists. It is also a good place to document why there is NOT.

An example of a performance failure is the following:

 int x = 2; if x != 2 { return true; } else { return false; } 

The fact is that it always checks the if clause, fails and therefore must check the else clause.

Edit: if the else clause does nothing, the compiler will skip it - it will just come in handy for reading by other developers. it can also make your code more concise:

 if(x=2) { doThis(); } if(x!=2){ doThat(); } 

can be confused and easily combined with:

 if(x==2){ doThis(); } else { doThat(); } 
0
source share

In addition, it is best to have one return path rather than multiple return paths.

 if (myCondition) { return true;} else { return false;} 

Must be:

 bool myResult = false; if (myCondition) myResult = true; return myResult; 

When you start introducing multiple return paths into the same method, even simple methods, you exponentially complicate debugging.

As far as β€œbetter”, I believe that the compiler processes both the same (with and without), since else is a single statement.

0
source share

All Articles