解析Linux中的 likely 和 unlikely

Posted smartvxworks

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解析Linux中的 likely 和 unlikely相关的知识,希望对你有一定的参考价值。

      

目录

1.函数原型

2.使用该函数的作用

2.1 通过汇编代码查看编译器实际动作汇编代码如下:

3.总结

4.参考


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

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

1.函数原型

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

long __builtin_expect (long exp, long c)

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

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

2.使用该函数的作用

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

if (unlikely(x)) 
	do_something();

return x;

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

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

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

汇编代码如下:

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

3.总结

        linux内核里的likely和unlikely实际上功能和if是一样的的,likely和unlikely在编译阶段,编译器对其进行了优化,减少分支,使得CPU执行更高效!

4.参考

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 解析

以上是关于解析Linux中的 likely 和 unlikely的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核中的c语言:likely()unlikely()

Linux内核中的c语言:likely()unlikely()

Linux 内核源码中likely()和unlikely()

Linux 内核源码中likely()和unlikely()

likely(x)与unlikely(x)函数,即__builtin_expect的使用

AFNetworking 同步调用(like/unlike)