likely和unlikely是gcc扩展的跟处理器相关的宏:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
现在处理器都是流水线的,有些里面有多个逻辑运算单元,系统可以提前取多条指令进行并行处理,但遇到跳转时,则需要重新取指令,这相对于不用重新去指令就降低了速度。所以就引入了likely和unlikely,目的是增加条件分支预测的准确性,cpu会提前装载后面的指令,遇到条件转移指令时会提前预测并装载某个分支的指令。unlikely 表示你可以确认该条件是极少发生的,相反likely表示该条件多数情况下会发生。编译器会产生相应的代码来优化cpu执行效率。
因此程序员在编写代码时可以根据判断条件发生的概率来优化处理器的取指操作。
从表面上看if(likely(value)) == if(value),if(unlikely(value)) == if(value)
内核2.2.26的头文件include/linux/compiler.h中有宏定义
/*
* Generic compiler-dependent macros required for kernel
* build go below this comment. Actual compiler/compiler version
* specific implementations come from the above header files
*/
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
__builtin_expect是gcc的一个预处理命令,其解释如下:
long __builtin_expect (long exp, long c)
You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (‘-fprofile-arcs’), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.
The return value is the value of exp, which should be an integral expression. The value of c must be a compile-time constant. The semantics of the built-in are that it is expected that exp == c.