kernel 源码中的 likely() 和 unlikely()

来源:互联网 发布:微信加好友软件靠谱吗 编辑:程序博客网 时间:2024/05/18 01:03

这两个都是宏,展开形式如下:

#define likely(x)   __builtin_expect(!!(x), 1)#define unlikely(x) __builtin_expect(!!(x), 0)

(现在的源代码中可能还加入了ftrace的功能,用于统计预测成功率,改善程序性能,参见ftrace简介)
__builtin_expect(!!(x), 1)用来表示程序员预测x值为1的可能性比较大,这可以帮助编译器来优化汇编代码。
比如,下面的代码:

int main(int argc, char *argv[]){//如果使用编译时常量,经过优化后,if语句可能就不会翻译了,直接翻译正确的执行路径    int a = atoi(argv[1]);    if (__builtin_expect(!!(a == 1), 1))    {        a++;    }    else    {        a--;    }    int b = atoi(argv[2]);    if (__builtin_expect(!!(b == 1), 0))    {        b++;    }    else    {        b--;    }    printf("%d\n", a + b);    return 0;}

使用gcc -S -O2 进行汇编,得到关键部分代码如下:

//得到a        movq    8(%rsi), %rdi        call    atoi//我们预测a == 1,如果a != 1,发生跳转        cmpl    $1, %eax        jne     .L8        movl    $2, %ebp.L2://得到b        movq    16(%rbx), %rdi        xorl    %eax, %eax        call    atoi//我们预测b != 1,如果b == 1,发生跳转        cmpl    $1, %eax        je      .L5        subl    $1, %eax

可见,对if语句翻译成汇编代码后的跳转策略发生了变化,如果实际结果与预期相同,则不发生跳转,否则发生跳转。发生跳转会带来什么问题呢?会清空处理器流水线,可能带来一些性能上的损失。

0 0
原创粉丝点击