在源码中,宏likely和unlikely 是这么定义的(位于include/linux/compiler.h):
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
要理解宏likely和unlikely ,很明显必须理解__builtin_expect。__builtin_expect是GCC(version>=2.9)引进的宏,其作用就是帮助编译器判断条件跳转的预期值,避免跳转造成时间浪费。拿下面的代码来说:
if (likely(acat == 1)) //表示大多数情况下if里面是真,程序大多数直接执行if里面的程序
而
if (unlikely (thread_memory_magazine1_is_empty (tmem, ix)))//表示大多数情况if里面为假,程序大多数直接执行else里面的程序
两段代码编译生成的汇编语句所使用到的跳转指令不一样,__builtin_expect实际上是为了满足在大多数情况不执行跳转指令,所以__builtin_expect仅仅是告诉编译器优化,并没有改变其对真值的判断。
示例:
//test_builtin_expect.c #define LIKELY(x) __builtin_expect(!!(x), 1) #define UNLIKELY(x) __builtin_expect(!!(x), 0) int test_likely(int x) { if(LIKELY(x)) { x = 5; } else { x = 6; } return x; } int test_unlikely(int x) { if(UNLIKELY(x)) { x = 5; } else { x = 6; } return x; }
[lammy@localhost test_builtin_expect]$ gcc -fprofile-arcs -O2 -c test_builtin_expect.c [lammy@localhost test_builtin_expect]$ objdump -d test_builtin_expect.o test_builtin_expect.o: file format elf32-i386 Disassembly of section .text: 00000000 <test_likely>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 8b 45 08 mov 0x8(%ebp),%eax 6: 83 05 38 00 00 00 01 addl $0x1,0x38 d: 83 15 3c 00 00 00 00 adcl $0x0,0x3c 14: 85 c0 test %eax,%eax 16: 74 15 je 2d <test_likely+0x2d>//主要看这里 18: 83 05 40 00 00 00 01 addl $0x1,0x40 1f: b8 05 00 00 00 mov $0x5,%eax 24: 83 15 44 00 00 00 00 adcl $0x0,0x44 2b: 5d pop %ebp 2c: c3 ret 2d: 83 05 48 00 00 00 01 addl $0x1,0x48 34: b8 06 00 00 00 mov $0x6,%eax 39: 83 15 4c 00 00 00 00 adcl $0x0,0x4c 40: 5d pop %ebp 41: c3 ret 42: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi 49: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi 00000050 <test_unlikely>: 50: 55 push %ebp 51: 89 e5 mov %esp,%ebp 53: 8b 55 08 mov 0x8(%ebp),%edx 56: 83 05 20 00 00 00 01 addl $0x1,0x20 5d: 83 15 24 00 00 00 00 adcl $0x0,0x24 64: 85 d2 test %edx,%edx 66: 75 15 jne 7d <test_unlikely+0x2d>//主要看这里 68: 83 05 30 00 00 00 01 addl $0x1,0x30 6f: b8 06 00 00 00 mov $0x6,%eax 74: 83 15 34 00 00 00 00 adcl $0x0,0x34 7b: 5d pop %ebp 7c: c3 ret 7d: 83 05 28 00 00 00 01 addl $0x1,0x28 84: b8 05 00 00 00 mov $0x5,%eax 89: 83 15 2c 00 00 00 00 adcl $0x0,0x2c 90: 5d pop %ebp 91: c3 ret 92: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi 99: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi 000000a0 <_GLOBAL__I_65535_0_test_likely>: a0: 55 push %ebp a1: 89 e5 mov %esp,%ebp a3: 83 ec 08 sub $0x8,%esp a6: c7 04 24 00 00 00 00 movl $0x0,(%esp) ad: e8 fc ff ff ff call ae <_GLOBAL__I_65535_0_test_likely+0xe> b2: c9 leave b3: c3 ret [lammy@localhost test_builtin_expect]$