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

本文介绍了GCC编译器中的__builtin_expect宏如何帮助优化代码性能。通过预测条件语句的结果,编译器可以生成更高效的汇编代码,减少不必要的处理器流水线清空,从而提升程序运行效率。

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

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值