条件语句中的性能
Performance in conditional statements
我注意到我正在处理的代码使用了如下条件:
if(A != val) {
// code B
}
if(B != val) {
// code A
}
但对我来说,阅读下面的相同代码要容易得多。也许是个人喜好。
if( B == val) {
//code B
}
if( A == val) {
//code A
}
这是一个对延迟非常敏感的代码,那么两者之间是否存在性能差异? != 或 == 之间有性能差异吗?或 > 或 < 就此而言?另外,我意识到这段代码为第三个条件留出了空间,尽管我很确定代码只留下了 2 条可能的路径,所以 if/else 更合适。
非常感谢。
无论您检查相等性还是任何类型的不等性,您的汇编代码中都会有一个条件跳转。性能差异应该是微不足道的。
尽管编写无分支代码可能是有益的,请参见例如Why is it faster to process a sorted array than an unsorted array?.
这里是在你使用 != 的条件下的汇编代码,注意我在 if 语句中添加了一个 printf 以便从 gdb 获得更好的输出:
0x0000000000400526 <+0>: push rbp
0x0000000000400527 <+1>: mov rbp,rsp
0x000000000040052a <+4>: sub rsp,0x10
0x000000000040052e <+8>: mov DWORD PTR [rbp-0xc],0x0
0x0000000000400535 <+15>: mov DWORD PTR [rbp-0x8],0x1
0x000000000040053c <+22>: mov DWORD PTR [rbp-0x4],0x1
0x0000000000400543 <+29>: mov eax,DWORD PTR [rbp-0xc]
0x0000000000400546 <+32>: cmp eax,DWORD PTR [rbp-0x4]
0x0000000000400549 <+35>: **je** 0x400555 <main+47>
0x000000000040054b <+37>: mov edi,0x4005f4
0x0000000000400550 <+42>: call 0x400400 <puts@plt>
0x0000000000400555 <+47>: mov eax,DWORD PTR [rbp-0x8]
0x0000000000400558 <+50>: cmp eax,DWORD PTR [rbp-0x4]
0x000000000040055b <+53>: **je** 0x400567 <main+65>
0x000000000040055d <+55>: mov edi,0x4005f4
0x0000000000400562 <+60>: call 0x400400 <puts@plt>
0x0000000000400567 <+65>: mov eax,0x0
0x000000000040056c <+70>: leave
0x000000000040056d <+71>: ret
虽然这是为了 ==:
0x0000000000400526 <+0>: push rbp
0x0000000000400527 <+1>: mov rbp,rsp
0x000000000040052a <+4>: sub rsp,0x10
0x000000000040052e <+8>: mov DWORD PTR [rbp-0xc],0x0
0x0000000000400535 <+15>: mov DWORD PTR [rbp-0x8],0x1
0x000000000040053c <+22>: mov DWORD PTR [rbp-0x4],0x1
0x0000000000400543 <+29>: mov eax,DWORD PTR [rbp-0x8]
0x0000000000400546 <+32>: cmp eax,DWORD PTR [rbp-0x4]
0x0000000000400549 <+35>: **jne** 0x400555 <main+47>
0x000000000040054b <+37>: mov edi,0x4005f4
0x0000000000400550 <+42>: call 0x400400 <puts@plt>
0x0000000000400555 <+47>: mov eax,DWORD PTR [rbp-0xc]
0x0000000000400558 <+50>: cmp eax,DWORD PTR [rbp-0x4]
0x000000000040055b <+53>: **jne** 0x400567 <main+65>
0x000000000040055d <+55>: mov edi,0x4005f4
0x0000000000400562 <+60>: call 0x400400 <puts@plt>
0x0000000000400567 <+65>: mov eax,0x0
0x000000000040056c <+70>: leave
0x000000000040056d <+71>: ret
您可能会注意到,唯一的区别是 je(如果相等则跳转)或 jne(如果不相等则跳转)的用法,因此就性能而言,您可以说它们完全相同
我注意到我正在处理的代码使用了如下条件:
if(A != val) {
// code B
}
if(B != val) {
// code A
}
但对我来说,阅读下面的相同代码要容易得多。也许是个人喜好。
if( B == val) {
//code B
}
if( A == val) {
//code A
}
这是一个对延迟非常敏感的代码,那么两者之间是否存在性能差异? != 或 == 之间有性能差异吗?或 > 或 < 就此而言?另外,我意识到这段代码为第三个条件留出了空间,尽管我很确定代码只留下了 2 条可能的路径,所以 if/else 更合适。
非常感谢。
无论您检查相等性还是任何类型的不等性,您的汇编代码中都会有一个条件跳转。性能差异应该是微不足道的。
尽管编写无分支代码可能是有益的,请参见例如Why is it faster to process a sorted array than an unsorted array?.
这里是在你使用 != 的条件下的汇编代码,注意我在 if 语句中添加了一个 printf 以便从 gdb 获得更好的输出:
0x0000000000400526 <+0>: push rbp
0x0000000000400527 <+1>: mov rbp,rsp
0x000000000040052a <+4>: sub rsp,0x10
0x000000000040052e <+8>: mov DWORD PTR [rbp-0xc],0x0
0x0000000000400535 <+15>: mov DWORD PTR [rbp-0x8],0x1
0x000000000040053c <+22>: mov DWORD PTR [rbp-0x4],0x1
0x0000000000400543 <+29>: mov eax,DWORD PTR [rbp-0xc]
0x0000000000400546 <+32>: cmp eax,DWORD PTR [rbp-0x4]
0x0000000000400549 <+35>: **je** 0x400555 <main+47>
0x000000000040054b <+37>: mov edi,0x4005f4
0x0000000000400550 <+42>: call 0x400400 <puts@plt>
0x0000000000400555 <+47>: mov eax,DWORD PTR [rbp-0x8]
0x0000000000400558 <+50>: cmp eax,DWORD PTR [rbp-0x4]
0x000000000040055b <+53>: **je** 0x400567 <main+65>
0x000000000040055d <+55>: mov edi,0x4005f4
0x0000000000400562 <+60>: call 0x400400 <puts@plt>
0x0000000000400567 <+65>: mov eax,0x0
0x000000000040056c <+70>: leave
0x000000000040056d <+71>: ret
虽然这是为了 ==:
0x0000000000400526 <+0>: push rbp
0x0000000000400527 <+1>: mov rbp,rsp
0x000000000040052a <+4>: sub rsp,0x10
0x000000000040052e <+8>: mov DWORD PTR [rbp-0xc],0x0
0x0000000000400535 <+15>: mov DWORD PTR [rbp-0x8],0x1
0x000000000040053c <+22>: mov DWORD PTR [rbp-0x4],0x1
0x0000000000400543 <+29>: mov eax,DWORD PTR [rbp-0x8]
0x0000000000400546 <+32>: cmp eax,DWORD PTR [rbp-0x4]
0x0000000000400549 <+35>: **jne** 0x400555 <main+47>
0x000000000040054b <+37>: mov edi,0x4005f4
0x0000000000400550 <+42>: call 0x400400 <puts@plt>
0x0000000000400555 <+47>: mov eax,DWORD PTR [rbp-0xc]
0x0000000000400558 <+50>: cmp eax,DWORD PTR [rbp-0x4]
0x000000000040055b <+53>: **jne** 0x400567 <main+65>
0x000000000040055d <+55>: mov edi,0x4005f4
0x0000000000400562 <+60>: call 0x400400 <puts@plt>
0x0000000000400567 <+65>: mov eax,0x0
0x000000000040056c <+70>: leave
0x000000000040056d <+71>: ret
您可能会注意到,唯一的区别是 je(如果相等则跳转)或 jne(如果不相等则跳转)的用法,因此就性能而言,您可以说它们完全相同