Performance Difference of "If If" VS "If Else If"

Performance difference of if if vs if else if

Assuming simple types (in this case, I used int) and no funny business (didn't redefine operator= for int), at least with GCC 4.6 on AMD64, there is no difference. The generated code is identical:

0000000000000000 <case_1>:                                   0000000000000040 <case_2>:
0: 85 ff test %edi,%edi 40: 85 ff test %edi,%edi
2: 74 14 je 18 <case_1+0x18> 42: 74 14 je 58 <case_2+0x18>
4: 83 ff 01 cmp $0x1,%edi 44: 83 ff 01 cmp $0x1,%edi
7: 74 27 je 30 <case_1+0x30> 47: 74 27 je 70 <case_2+0x30>
9: 83 ff 02 cmp $0x2,%edi 49: 83 ff 02 cmp $0x2,%edi
c: 74 12 je 20 <case_1+0x20> 4c: 74 12 je 60 <case_2+0x20>
e: 66 90 xchg %ax,%ax 4e: 66 90 xchg %ax,%ax
10: f3 c3 repz retq 50: f3 c3 repz retq
12: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 52: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
18: 31 c0 xor %eax,%eax 58: 31 c0 xor %eax,%eax
1a: e9 00 00 00 00 jmpq 1f <case_1+0x1f> 5a: e9 00 00 00 00 jmpq 5f <case_2+0x1f>
1f: 90 nop 5f: 90 nop
20: 31 c0 xor %eax,%eax 60: 31 c0 xor %eax,%eax
22: e9 00 00 00 00 jmpq 27 <case_1+0x27> 62: e9 00 00 00 00 jmpq 67 <case_2+0x27>
27: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 67: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
2e: 00 00 6e: 00 00
30: 31 c0 xor %eax,%eax 70: 31 c0 xor %eax,%eax
32: e9 00 00 00 00 jmpq 37 <case_1+0x37> 72: e9 00 00 00 00 jmpq 77 <case_2+0x37>
37: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
3e: 00 00

The extra instruction at the end of case_1 is just for padding (to get the next function aligned).

This isn't really surprising, figuring out that p isn't changed in that function is fairly basic optimization. If p could be changed (e.g., passed-by-reference or pointer to the various do_… functions, or was a reference or pointer itself, so there could be an alias) then the behavior is different, and of course the generated code would be too.

If statement vs if-else statement, which is faster?

TL;DR: In unoptimized code, if without else seems irrelevantly more efficient but with even the most basic level of optimization enabled the code is basically rewritten to value = condition + 5.


I gave it a try and generated the assembly for the following code:

int ifonly(bool condition, int value)
{
value = 5;
if (condition) {
value = 6;
}
return value;
}

int ifelse(bool condition, int value)
{
if (condition) {
value = 6;
} else {
value = 5;
}
return value;
}

On gcc 6.3 with optimizations disabled (-O0), the relevant difference is:

 mov     DWORD PTR [rbp-8], 5
cmp BYTE PTR [rbp-4], 0
je .L2
mov DWORD PTR [rbp-8], 6
.L2:
mov eax, DWORD PTR [rbp-8]

for ifonly, while ifelse has

 cmp     BYTE PTR [rbp-4], 0
je .L5
mov DWORD PTR [rbp-8], 6
jmp .L6
.L5:
mov DWORD PTR [rbp-8], 5
.L6:
mov eax, DWORD PTR [rbp-8]

The latter looks slightly less efficient because it has an extra jump but both have at least two and at most three assignments so unless you really need to squeeze every last drop of performance (hint: unless you are working on a space shuttle you don't, and even then you probably don't) the difference won't be noticeable.

However, even with the lowest optimization level (-O1) both functions reduce to the same:

test    dil, dil
setne al
movzx eax, al
add eax, 5

which is basically the equivalent of

return 5 + condition;

assuming condition is zero or one.
Higher optimization levels don't really change the output, except they manage to avoid the movzx by efficiently zeroing out the EAX register at the start.


Disclaimer: You probably shouldn't write 5 + condition yourself (even though the standard guarantees that converting true to an integer type gives 1) because your intent might not be immediately obvious to people reading your code (which may include your future self). The point of this code is to show that what the compiler produces in both cases is (practically) identical. Ciprian Tomoiaga states it quite well in the comments:

a human's job is to write code for humans and let the compiler write code for the machine.

Performance Differences of Nested If Else Statements vs. ElseIf Statements

I've decompiled the two and it seem to be generating the same code (using ildasm). This is a very simple If statment, might get different result for different If. I would suggest you do the same with your code and see.

Module Module1

Sub Main()

Dim a As Integer
Dim i As Integer = 1

If i = 1 Then
a = 9
ElseIf i = 2 Then
a = 8
ElseIf i = 3 Then
a = 7
Else
a = 6
End If

End Sub

End Module

.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 30 (0x1e)
.maxstack 2
.locals init ([0] int32 a,
[1] int32 i)
IL_0000: ldc.i4.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: ldc.i4.1
IL_0004: bne.un.s IL_000b
IL_0006: ldc.i4.s 9
IL_0008: stloc.0
IL_0009: br.s IL_001d
IL_000b: ldloc.1
IL_000c: ldc.i4.2
IL_000d: bne.un.s IL_0013
IL_000f: ldc.i4.8
IL_0010: stloc.0
IL_0011: br.s IL_001d
IL_0013: ldloc.1
IL_0014: ldc.i4.3
IL_0015: bne.un.s IL_001b
IL_0017: ldc.i4.7
IL_0018: stloc.0
IL_0019: br.s IL_001d
IL_001b: ldc.i4.6
IL_001c: stloc.0
IL_001d: ret
} // end of method Module1::Main

And the other one

Module Module1

Sub Main()

Dim a As Integer
Dim i As Integer = 1

If i = 1 Then
a = 9
Else
If i = 2 Then
a = 8
Else
If i = 3 Then
a = 7
Else
a = 6
End If
End If
End If

End Sub

End Module

.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 30 (0x1e)
.maxstack 2
.locals init ([0] int32 a,
[1] int32 i)
IL_0000: ldc.i4.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: ldc.i4.1
IL_0004: bne.un.s IL_000b
IL_0006: ldc.i4.s 9
IL_0008: stloc.0
IL_0009: br.s IL_001d
IL_000b: ldloc.1
IL_000c: ldc.i4.2
IL_000d: bne.un.s IL_0013
IL_000f: ldc.i4.8
IL_0010: stloc.0
IL_0011: br.s IL_001d
IL_0013: ldloc.1
IL_0014: ldc.i4.3
IL_0015: bne.un.s IL_001b
IL_0017: ldc.i4.7
IL_0018: stloc.0
IL_0019: br.s IL_001d
IL_001b: ldc.i4.6
IL_001c: stloc.0
IL_001d: ret
} // end of method Module1::Main

I would suggest to use the one that is easier to read.

What is faster: many ifs, or else if?

Yes, use an else if, consider the following code:

if(predicateA){
//do Stuff
}
if(predicateB){
// do more stuff
}

of

if(predicateA){
//
}
else if(predicateB){
//
}

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.

Difference between chained if's and else if

In your specific example they are the same (note: question edited; now they are not). Anyway consider something like:

Example 1: Modifying variables

if (age > 18) age = 17; // executes
if (age < 18) ... // executes!

Now you can see this would behave differently than

age = 19;
if (age > 18) age = 17; // executes
else if (age < 18) ... // skipped!

Example 2: Overlapping conditions

Or as @cubic mentions, if the conditions overlap, there will also be a difference.

age = 20;
if (age > 19) ...; // executes
if (age > 17) ...; // executes!

versus:

age = 20;
if (age > 19) ...; // executes
else if (age > 17) ...; // skipped!

If Else VS Multiple If Statements

Using only if, interpreter or whatever will test all conditions but if you use else if (if possible) then on passing any condition , next else if will not be tested or checked.

if (age < 10){
// do something
}
if (age < 20 && age > 10){
// do something
}
if (age < 30 && age > 20){
// do something
}

All conditions will be tested/compared

but in this scenario

if (age < 10){
// do something
}
else if (age < 20 && age > 10){
// do something
}
else if (age < 30 && age > 20){
// do something
}

if age is 5, only first condition will be tested.

Performance difference between two if statements?

With the given example, there won't be any difference in performance, even with if a == 0 and b == 0 and c == 0: it won't check b == 0 when the initial condition a == 0 itself is False. But considering the minimal lines of code & readability, if a == 0 and b == 0 and c == 0: would be the better option.

Case vs If Else If: Which is more efficient?

It seems that the compiler is better in optimizing a switch-statement than an if-statement.

The compiler doesn't know if the order of evaluating the if-statements is important to you, and can't perform any optimizations there. You could be calling methods in the if-statements, influencing variables. With the switch-statement it knows that all clauses can be evaluated at the same time and can put them in whatever order is most efficient.

Here's a small comparison:

http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx



Related Topics



Leave a reply



Submit