浅尝辄止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 
//这个函数的内容请忽略,写复杂点只是为了不被优化
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 :
   0:   e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
   ...
   34:   e49df004        pop     {pc}            ; (ldr pc, [sp], #4)

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

00000064 :
  64:   e3500000        cmp     r0, #0
  68:   e92d4008        push    {r3, lr}
  6c:   1a000003        bne     80     ;0时不跳转
  70:   e3e00031        mvn     r0, #49 ; 0x31
  74:   ebfffffe        bl      0 
  78:   e3e00031        mvn     r0, #49 ; 0x31
  7c:   e8bd8008        pop     {r3, pc}
  80:   e3a00e19        mov     r0, #400        ; 0x190
  84:   ebfffffe        bl      0 
  88:   e3a00e19        mov     r0, #400        ; 0x190
  8c:   e8bd8008        pop     {r3, pc}

你可能感兴趣的:(浅尝辄止34-likely和unlikely)