解析Linux中的 likely 和 unlikely

22 篇文章 0 订阅
7 篇文章 0 订阅

Linux 中多处出现 likely 和 unlikely 的使用,它们的定义如下:

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

函数原型

__builtin_expect 是 GCC 提供的内置函数 (built-in functions),函数原型是

long __builtin_expect (long exp, long c)

函数的返回值是 exp,它告诉编译器, 代码期望的是 exp == c 。

注意:代码中!!,并不是特殊符号,只是两次取反,通过这种技巧,可以将任意量转换为0或1。0 为 0,非 0 值为1。

使用该函数的作用

现代处理器的工作远超前于当前指令,比如从内存读新指令,译码指令等。只要指令遵循的是简单的顺序,那么这种指令流水线化就能很好的工作。当遇到分支的时候,处理器必须猜测分支该往哪个方向走,如果猜测错误,就会损失处理器的性能,因此需要分支预测技术。
__builtin_expect 就是用来为处理器的分支预测提供信息,帮助处理器进行分支预测。

if (unlikely(x)) {
	do_something();
}
return x;

编译器会让主分支是概率最大的分支,尽量减少程序跳转的情况。以上代码会被编译器调整为如下的汇编逻辑。

if(x)
	goto L1;
	return x;
L1:
	do_something();
	return x;

通过汇编代码查看编译器实际动作

int normal_fun(int x)
{
    if (x) {
        do_something();
    }

    return x;
}

int unlikely_fun(int x) 
{
    if(__builtin_expect(x, 0)) {
        do_something();
    }

    return x;
}

int likely_fun(int x) 
{
    if(__builtin_expect(x, 1)) {
        do_something();
    }

    return x;
}

汇编代码如下:

normal_fun:
        pushq   %rbx
        movl    %edi, %ebx
        testl   %edi, %edi
        jne     .L4		;normal 版本采用默认的分支预测
.L2:
        movl    %ebx, %eax
        popq    %rbx
        ret
.L4:
        movl    $0, %eax
        call    do_something
        jmp     .L2
unlikely_fun:			
        pushq   %rbx
        movl    %edi, %ebx
        testl   %edi, %edi
        jne     .L8		;使等于1的情况作为跳转分支。
.L6:
        movl    %ebx, %eax
        popq    %rbx
        ret
.L8:
        movl    $0, %eax
        call    do_something
        jmp     .L6
likely_fun:
        pushq   %rbx
        movl    %edi, %ebx
        testl   %edi, %edi
        je      .L10	;使等于1的情况作为主分支。
        movl    $0, %eax
        call    do_something
.L10:
        movl    %ebx, %eax
        popq    %rbx
        ret

参考:
Other Built-in Functions Provided by GCC
How do the likely/unlikely macros in the Linux kernel work and what is their benefit?
GCC __builtin_expect 解析

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lylhw13_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值