views:

390

answers:

7

Is it better to have if / else if, if every block in the if statement returns, or is it better to have a chain of ifs? To be specific, which if fastest:

A:

if (condition1) {
  code1;
  return a;
}
if (condition2) {
  code2;
  return b;
}
//etc...

B:

if (condition1) {
  code1;
  return a;
}
else if (condition2) {
  code2;
  return b;
}
//etc...
+40  A: 

It makes no difference, and this is a needless attempt at micro-optimization.

Mike Daniels
+1 Any decent compiler will notice that the else is not needed.
Preet Sangha
It's not even a micro-optimization. It's a 0-optimization.
Steve Jessop
You're right. Edited to clarify. :)
Mike Daniels
I was soooo slow. Maybe because I wanted to include asm-like code. The only difference is an extra instruction.
Anzurio
no, the difference should be exactly zero instructions. At least assuming a sane compiler
jalf
Sometimes code is in a loop, and speed matters. I've looked into similar cases a few times trying to nail 60fps. No way to know if this is needless optimization or not. It probably is, though. :-)
Nosredna
You can't always assume sane compilers. Often when people ask about speed, they are using an embedded system with a lousy compiler. It's happened to me more than once. The world is bigger than the x86 and ARM families. Of course, an embedded programmer could just compile both and look at the opcodes generated and do the timings.
Nosredna
@jalf, in MSVC90 I'm totally sure there's that extra instruction at least when not optimization is present.
Anzurio
@Nosredna: True, but if we were to assume the compiler is insane, we couldn't say anything without seeing the output of the exact compiler the OP is using. Failing to specify the exact architecture/compiler you are using in the OP means you're OK with an answer that covers theoretical/logical/normal/sane case.
Mehrdad Afshari
++ There may be a performance issue, but it is not in that code.
Mike Dunlavey
Even with a very basic non-optimizing compiler, there would not be any speed difference. "else" is not a statement that takes time. It just dictates where to jump to when the condition is not satisfied. A very primitive compiler might add a useless jmp-statement (jumping to the first statement after the else block) at the end of the if block, right after the first return statement.
ammoQ
A: 

This should perform the same in the optimized builds. If not, then something else is likely preventing the compiler from doing the "right thing".

Robbotic is incorrect. In both instances, if the first clause is true, then the subsiquent statements will not be executed (evaluated).

Note, be sure to measure - you may be optimizing the wrong thing.

Foredecker
+12  A: 

The C standard does not dictate what machine language gets created based on the C code. You can sometimes make assumptions if you understand the underlying architecture but even that is unwise.

The days are long past where CPUs are simple beasts now that they have pipelining, multiple levels of caches and all sorts of other wondrous things to push their speed to the limit.

You should not be worrying about this level of optimization until you have a specific problem (some would say "at all").

Write your code to be readable. That should be rule number 1, 2 and 3. Which do you think is the greatest problem in software development, code running at 99.5% of it's maximum speed or developers spending days trying to figure out and/or fix what a colleague (or even themselves) did six months ago?

My advice is to worry about performance only when you find it's a problem, then benchmark on the target platforms to see where the greatest improvement can be gained. A 1% improvement in a if statement is likely to be dwarfed by choosing a better algorithm elsewhere in your code (other things, such as number of times the code is called, being equal of course). Optimization should always be targeted to get the best bang-per-buck.

paxdiablo
++ Occasionally if I'm doing graphics or something, and some routine is an actual hotspot and would benefit from cycle-squeezing, I might care. The other 99.99% of the time, performance problems are caused by excess calls to functions that do a lot more than the coder thinks they will.
Mike Dunlavey
+1  A: 

With those returns, the else is superflous. The compiler is likely smart enough to figure this out.

I suspect the compiler will generate the same code for both. Disassemble it and see.

In any case, examining the output of the compiler and empirical performance testing is the only way to be sure.

smcameron
+2  A: 

They should be equivalent on most architectures. The instructions generated are probably still the same bne, cmps and rets.

What might help is if you use a switch/case instead of if statement.

Unknown
heh, brilliant! didn't even consider that..
Claudiu
+3  A: 

I don't really think it is a big difference if any:

For the A case:

if (condition){
    //conditionOp
    //cmp ... , ...
    //jxx :toEndIf
    code;
    return bar;
    //mov eax, bar
    //jmp :toEnd
}
if(condition){
    //conditionOp
    //cmp ... , ...
    //jxx :toEndIf
    code;
    return bar;
    //mov eax, bar
    //jmp :toEnd
}

For the B case:

if(condition){
    //conditionOp
    //cmp ... , ...
    //jxx :toElse + 1
    code;
    return bar;
    //mov eax , bar
    //jmp :toEnd
} else 
    //jmp :endElse 
if (condition2){
    //conditionOp
    //cmp ... , ...
    //jxx :endElse
    code;
    return bar;
    //mov eax, bar
    //jmp :toEnd
}

Thus, using the B case, one extra instruction is added. Though, optimizing for size may get rid of that.

Anzurio
+1 for going the extra yards but you may want to state it's for a specific CPU/compiler/optimization-level/phase-of-moon.
paxdiablo
For example, GCC does not emit code like this for x86, even without any optimisation.
Steve Jessop
+1  A: 

Write a simple test program to measure this and find out - but yes this is needless optimization.

Jeremy Cron