浅尝辄止34-likely和unlikely

如果你读过Linux代码的非驱动部分,一定会见过likely和unlikely,今天说说它们。

浅尝

它们实际上是2个宏,__builtin_expect是gcc编译优化的build-in function,尽管我没有在gcc官方网页上找到说明,不过实践上确实好用。字面的意思就是likely中的值为非零的概率大,unlikely中的值为零的概率大,编译器要根据这个概率优化指令。内核代码执行的重复度很高,所以每一条指令的优化都有意义。

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

代码演示

#include <stdio.h>
//这个函数的内容请忽略,写复杂点只是为了不被优化
void func(int i){
    volatile int x = i;
    x++;
    i = x + 100;     
    printf("%d", i);
}
int func0(int value){
    int ret;
    value = !!value;
    if (__builtin_expect(value, 1)){
        ret = 100;
        ret = ret + ret;
        ret = ret + ret;
        func(ret);
    }
    else{
        ret = 50;
        ret = 50 + ret;
        ret = 50 - ret;
        func(ret);
    }
    return ret;
}

int func1(int value){
    int ret;
    value = !!value;
    if (__builtin_expect(value, 0)){
        ret = 100;
        ret = ret + ret;
        ret = ret + ret;
        func(ret);
    }
    else{
        ret = 50;
        ret = 50 + ret;
        ret = 50 - ret;
        func(ret);
    }
    return ret;
}

编译

编译指令是gcc -c test.c -marm -O2 -o test.o,要加-O2,因为这东西是用来优化的,只有在优化编译时起作用。

反汇编

注意func0func1中的跳转条件,不跳转意味着流水线的顺畅运行,即效率较高。

00000000 <func>:
   0:   e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
   ...
   34:   e49df004        pop     {pc}            ; (ldr pc, [sp], #4)

00000038 <func0>:
  38:   e3500000        cmp     r0, #0
  3c:   e92d4008        push    {r3, lr}
  40:   0a000003        beq     54 <func+0x54>    ;非0时不跳转
  44:   e3a00e19        mov     r0, #400        ; 0x190
  48:   ebfffffe        bl      0 <func>
  4c:   e3a00e19        mov     r0, #400        ; 0x190
  50:   e8bd8008        pop     {r3, pc}
  54:   e3e00031        mvn     r0, #49 ; 0x31
  58:   ebfffffe        bl      0 <func>
  5c:   e3e00031        mvn     r0, #49 ; 0x31
  60:   e8bd8008        pop     {r3, pc}

00000064 <func1>:
  64:   e3500000        cmp     r0, #0
  68:   e92d4008        push    {r3, lr}
  6c:   1a000003        bne     80 <func+0x80>    ;0时不跳转
  70:   e3e00031        mvn     r0, #49 ; 0x31
  74:   ebfffffe        bl      0 <func>
  78:   e3e00031        mvn     r0, #49 ; 0x31
  7c:   e8bd8008        pop     {r3, pc}
  80:   e3a00e19        mov     r0, #400        ; 0x190
  84:   ebfffffe        bl      0 <func>
  88:   e3a00e19        mov     r0, #400        ; 0x190
  8c:   e8bd8008        pop     {r3, pc}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容