在Linux内核中可能()和不可能()
在2.6内核中,您可以看到任何可能()和不可能()的影子,所以它们为什么要使用它们之间的差异呢首先,它应该是明确的:
如果(可能(值))等于(值)
如果(不可能的(值))也等价于如果(值)
也就是说,从阅读和理解代码的角度来看,可能()和不可能()是相同的!
这两个宏在内核中定义如下:
#定义可能(x)__builtin_expect((x),1)
#定义可能__builtin_expect((x)(x),0)
__builtin_expect(GCC)(版本> = 2.96)程序员使用,目的是分支;编译器提供的信息,编译器可以对代码进行优化,减少跳转指令引起的性能退化。
__builtin_expect((x),1)表明,x的值是更真实。
__builtin_expect((x),0)表明,x的值是更可能是错误的。
也就是说,使用可能的(),在后面执行语句的机会更大,使用不太可能(),在后面执行更多语句的机会。
例如,下面的代码,作者认为,沪指不等于可能性下。
如果(可能(沪指!=下一步){
接下来>时间戳=现在;
…
其他{ }
…;
}
这样,在编译过程中,编译器将遵循更可能遵循更可能的代码的代码,从而减少指令跳转造成的性能下降。
下面是两个加深理解的例子:
第一个例子:1。C
Int testfun(int x)
{
如果(__builtin_expect(x,0)){
我们指导编译器,其他块更可能
x=5;
x=x;
其他{ }
x=6;
}
返回x;
}
在这个例子中,我们认为x更可能是0。
编译后的汇编指令,观察通过objdump。在我的2.4内核机器上,结果如下:
GCC O2- C C # 1。
# objdump -d example1. O
拆卸部分.文本:
00000000:
0:55推EBP
1:89 E5 MOV EBP ESP,
3:8B 4508 MOV 0x8(EBP),êx
6:85 C0测试êx,êx
8:7507 JNE 11
06000000乐章:B8 0x6美元,êx
F:C9离开
10:C3 RET
11:B8 19000000乐章为0x19,êx
16:EB F7 JMP F
你可以看到,编译器使用JNE(不等跳转)指令,并在其他块中的代码进行编码。
8:7507 JNE 11
06000000乐章:B8 0x6美元,êx
第二例子:例子。C
Int testfun(int x)
{
如果(__builtin_expect(x,1)){
我们指导编译器,块更可能
x=5;
x=x;
其他{ }
x=6;
}
返回x;
}
在这个例子中,我们认为x更可能小于0。
编译后的汇编指令,观察通过objdump。在我的2.4内核机器上,结果如下:
GCC O2- C C #例子。
# objdump -d例子啊
拆卸部分.文本:
00000000:
0:55推EBP
1:89 E5 MOV EBP ESP,
3:8B 4508 MOV 0x8(EBP),êx
6:85 C0测试êx,êx
8:7407乙脑11
19000000乐章:B8 0x19美元,êx
F:C9离开
10:C3 RET
11:B8 06000000乐章0x6美元,êx
16:EB F7 JMP F
编译器使用乙脑(等跳转)指令,if块中的代码后面跟着代码。
8:7407乙脑11
19000000乐章:B8 0x19美元,êx