1.问题引出
在内核代码的条件分支中的判断中,经常可以看到如下两条语句:
- /* ...... */
- if(unlikely(!something))
- /* ...... */
- if(likely(something))
- /* ...... */
追述一下可以看到有如下的宏定义:
- #define likely(x) __builtin_expect(!!(x), 1)
- #define unlikely(x) __builtin_expect(!!(x), 0)
2.查看gcc的info文档可以看到相关的说明
-- Built-in Function: long __builtin_expect (long EXP, long C)
You may use `__builtin_expect' to provide the compiler with branch
prediction information. In general, you should prefer to use
actual profile feedback for this (`-fprofile-arcs'), as
programmers are notoriously bad at predicting how their programs
actually perform. However, there are applications in which this
data is hard to collect.
The return value is the value of EXP, which should be an integral
expression. The value of C must be a compile-time constant. The
semantics of the built-in are that it is expected that EXP == C.
For example:
if (__builtin_expect (x, 0))
foo ();
would indicate that we do not expect to call `foo', since we
expect `x' to be zero. Since you are limited to integral
expressions for EXP, you should use constructions such as
if (__builtin_expect (ptr != NULL, 1))
error ();
when testing pointer or floating-point values.
大致的意思是这么说的:
你也许会使用'__builtin_expece'为编译器体统分支预测的信息。因为程序员在预测他们的程序
的执行流程和分支走向时,表现得臭名昭著地糟糕,所以在一般情况下,作为一个程序员的你也许
会更喜欢使用gcc的一个参数'-fprofile-arcs'来收集程序运行的关于执行流程和分支走向的实际反馈
信息。然而,从一些比较复杂的程序中收集这些信息是非常困难的。
该内建函数的返回值EXP必须是一个整型的表达式。C的值必须是一个常量。这个内建函数的意思就是
我期望得到的是 EXP == C。
例子:
- if (__builtin_expect (x, 0))
- foo ();
上面表示,我们不期望函数foo()会执行。因为我们期望x的值是0。因为EXP被限制为整型表达式,
所以如果你想测试指针(point)或者浮点数(floating-point),应该采用如下的语法结构:
- if (__builtin_expect (ptr != NULL, 1))
- error ();
上面当中,我们是期望error()函数会被执行。
3.再回到上面看看我们讨论的likely和unlikely
- #define likely(x) __builtin_expect(!!(x), 1)
- #define unlikely(x) __builtin_expect(!!(x), 0)
现在关于likely的返回值就很清晰了,就是期望为1,或者更加可能为1。
同样,unlikely的返回值就是更大可能性是0。
使用了!!是为了让x转化成bool型的。