Reputation: 13582
int i = 3;
Is there any performance difference between this code:
if(i == 2)
DoA();
if(i == 3)
DoB();
if(i == 4)
DoC();
And this code:
if(i == 2)
DoA();
else if(i == 3)
DoB();
else if(i == 4)
DoC();
I'm wondering if using optional ELSE affects how the CPU understands the code or not. I always think when we use the second approach, if i
is 2
then the CPU does not check the other two conditions, but in the first approach although the first condition is true (i == 2
) but the CPU does check the second and third conditions. Is this true?
Upvotes: 0
Views: 147
Reputation: 20027
If the 'DoX' are statements like 'a = b'; then it's possible that the first one executes faster and it's still possible that the compiler doesn't figure out the best option for mutually exclusive comparisons.
In some architectures, those three comparison could be translated to:
cmp a,2;
movlt b, c;
moveq c, d;
movgt e, f;
Iff these are very simple statements and the programmer helps a bit.
Some other practical ways to translate the problem for better performance is to use function pointers and make every step to guarantee, that there's no possibility of accessing the array out of range.
void (*do)()[]={ doA, doB, doC };
do[i]();
// mov eax, do[eax*4];
// call [eax]
Upvotes: 0
Reputation: 66573
You should not decide this on the basis of performance. The two versions of the code mean different things. You should use the one that is correct.
For example:
if (s == null)
{
// do something
s = GetNewValue();
}
if (s == "")
{
// do something else
}
Without an else
, this code means:
s
is null
s
to ""
(or s
was ""
to begin with), execute the second block.With an extra else
before the second if
, the code means:
s
is null
.s
wasn’t null
to begin with and it is equal to ""
.In cases where it makes no difference because the blocks don’t modify the variable you’re comparing against, use else
because it makes your code’s meaning explicit.
Upvotes: 3
Reputation: 8055
Here is IL code of your two statements:
.method private hidebysig static void m1() cil managed
{
.maxstack 2
.locals init (
[0] int32 i,
[1] bool CS$4$0000)
L_0000: nop
L_0001: ldc.i4.3
L_0002: stloc.0
L_0003: ldloc.0
L_0004: ldc.i4.2
L_0005: ceq
L_0007: ldc.i4.0
L_0008: ceq
L_000a: stloc.1
L_000b: ldloc.1
L_000c: brtrue.s L_0014
L_000e: call void ConsoleApplication1.Program::DoA()
L_0013: nop
L_0014: ldloc.0
L_0015: ldc.i4.3
L_0016: ceq
L_0018: ldc.i4.0
L_0019: ceq
L_001b: stloc.1
L_001c: ldloc.1
L_001d: brtrue.s L_0025
L_001f: call void ConsoleApplication1.Program::DoB()
L_0024: nop
L_0025: ldloc.0
L_0026: ldc.i4.4
L_0027: ceq
L_0029: ldc.i4.0
L_002a: ceq
L_002c: stloc.1
L_002d: ldloc.1
L_002e: brtrue.s L_0036
L_0030: call void ConsoleApplication1.Program::DoC()
L_0035: nop
L_0036: ret
}
.method private hidebysig static void m2() cil managed
{
.maxstack 2
.locals init (
[0] int32 i,
[1] bool CS$4$0000)
L_0000: nop
L_0001: ldc.i4.3
L_0002: stloc.0
L_0003: ldloc.0
L_0004: ldc.i4.2
L_0005: ceq
L_0007: ldc.i4.0
L_0008: ceq
L_000a: stloc.1
L_000b: ldloc.1
L_000c: brtrue.s L_0016
L_000e: call void ConsoleApplication1.Program::DoA()
L_0013: nop
L_0014: br.s L_003a
L_0016: ldloc.0
L_0017: ldc.i4.3
L_0018: ceq
L_001a: ldc.i4.0
L_001b: ceq
L_001d: stloc.1
L_001e: ldloc.1
L_001f: brtrue.s L_0029
L_0021: call void ConsoleApplication1.Program::DoB()
L_0026: nop
L_0027: br.s L_003a
L_0029: ldloc.0
L_002a: ldc.i4.4
L_002b: ceq
L_002d: ldc.i4.0
L_002e: ceq
L_0030: stloc.1
L_0031: ldloc.1
L_0032: brtrue.s L_003a
L_0034: call void ConsoleApplication1.Program::DoC()
L_0039: nop
L_003a: ret
}
Looks like the generated IL(s) are NOT same.
EDIT 1
In method m2()
:
L_0014: br.s L_003a
.
.
.
L_0027: br.s L_003a
then method 'm2()' is faster.
Upvotes: 1
Reputation: 21
Yes, use an else if, consider the following code:
if(predicateA){
//do Stuff
}
if(predicateB){
// do more stuff
}
or
if(predicateA){
//do stuff
}
else if(predicateB){
//do stuff
}
In the second case if predicateA is true, predicateB (and any further predicates) will not need to be evaluated (and so the whole code will execute faster), whereas in the first example if predicateA is true, predicateB will still always be evaluated, and you may also get some unexpected suprises if predicateA and predicateB are not mutually exclusive.
Upvotes: 0
Reputation:
Of course it does affect -- for better! It's totally the opposite of unecessary, since by using those elses the compiler will skip the other if-checks and get better performance.
But you shouldn't be worring about it, the difference in performance in your example is so minimal it's insignificant.
Upvotes: 2