在linux中的likely和unlikely

Linux中likely与unlikely宏
本文介绍了Linux中likely和unlikely宏的作用及实现原理。这些宏用于提供编译器分支预测信息,通过指导编译器优化代码顺序来提高程序运行效率。
在linux中的likely和unlikely
0

linux中判断语句经常会看到likely和unlikely,例如:

if(likely(value)){

}

else{

}

简单从表面上看if(likely(value)) == if(value),if(unlikely(value)) == if(value)。

这两个宏对程序运行结果没有影响,只是用于提高程序效率。其实现和gcc编译器密切相关。
具体点说,就是如果你觉得程序运行时候一般sndcmd|=0的可能性比较大,那么就加上likely的macro;反之则加unlikely。

也就是likely和unlikely是一样的,但是实际上执行是不同的,加likely的意识是value的值为真的可能

性更大一些,那么执行if的机会大,而unlikely表示value的值为假的可能性大一些,执行else机会大一些。

加上这种修饰,编译成二进制代码时likely使得if后面的执行语句紧跟着前面的程序,unlikely使得else后

面的语句紧跟着前面的程序,这样就会被cache预读取,增加程序的执行速度,likely和unlikely的实现在

include/linux/compiler.h中:

9 #if __GNUC__ == 2 && __GNUC_MINOR__ < 96
10 #define __builtin_expect(x, expected_value) (x)
11 #endif
12
13 #define likely(x) __builtin_expect((x),1)
14 #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. For example:
if (__builtin_expect (x, 0))
foo ();
would indicate that we do not expect to call foo, since we expect x to be zero. Since
you are limited to integral expressions for exp, you should use constructions such as
if (__builtin_expect (ptr != NULL, 1))
error ();
when testing pointer or floating-point values.

在 C/C++ 编程中,`likely` `unlikely` 是用于**优化分支预测**的宏,它们并不是语言内置关键字,而是通过编译器内置函数(如 GCC 或 Clang 的 `__builtin_expect`)实现的。它们帮助编译器生成更高效的机器码,特别是在条件判断中指明某个分支是“大概率发生”还是“小概率发生”。 --- ### ✅ `likely` `unlikely` 的等价实现 ```c #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) ``` #### 解释: - `__builtin_expect(expr, expected_value)`: - 告诉编译器 `expr` 的值**预期为** `expected_value`。 - 这只是一个提示,不影响逻辑,但会影响生成的汇编代码中分支的布局(热路径优化)。 - `!!(x)`: - 将任意表达式 `x` 转换为布尔值(0 或 1),确保传给 `__builtin_expect` 的是明确的布尔上下文。 - `likely(x)`:表示 `x` 很可能为真(即期望为 1) - `unlikely(x)`:表示 `x` 很不可能为真(即期望为 0) --- ### 📌 使用示例(C语言) ```c #include <stdio.h> #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) void test_function(int flag) { if (likely(flag == 1)) { printf("Flag is 1 (common case)\n"); } else if (unlikely(flag == 0)) { printf("Flag is 0 (rare case)\n"); } } ``` #### 汇编层面的影响(以 x86 为例): - `likely` 分支会被编译器放在“直通路径”(fall-through),减少跳转开销。 - `unlikely` 分支会生成跳转指令,避免污染指令缓存。 --- ### 💡 等价替代方式 虽然没有标准库直接提供 `likely/unlikely`,但在不同环境中有等价或近似机制: #### 1. **C++20 及以后:`[[likely]]` `[[unlikely]]` 属性(官方标准)** ```cpp void func(int flag) { if (flag == 1) [[likely]] { printf("Common case\n"); } else [[unlikely]] { printf("Rare case\n"); } } ``` > 这是现代 C++ 的标准写法,语义清晰且由编译器优化支持。 #### 2. **无提示(普通写法)——功能等价但无性能提示** ```c if (flag == 1) { // ... } else { // ... } ``` > 功能上完全一样,但编译器无法做最佳分支预测优化。 --- ### 🔍 实际应用场景 - 内核开发(Linux Kernel 大量使用 `likely/unlikely`) - 高性能服务中的错误处理(如 `if (unlikely(err)) handle_error();`) - 热路径优化 --- ### ❗注意事项 - 这些宏仅在 GCC/Clang 等支持 `__builtin_expect` 的编译器上有意义。 - 在 MSVC 中不支持 `__builtin_expect`,可使用条件编译规避: ```c #ifdef __GNUC__ #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else #define likely(x) (x) #define unlikely(x) (x) #endif ``` --- ### 总结 | 写法 | 是否等价 | 说明 | |------|----------|------| | `likely(x)` | ✅ 功能+优化等价 | 使用 `__builtin_expect(x, 1)` 提示编译器 | | `unlikely(x)` | ✅ 功能+优化等价 | 使用 `__builtin_expect(x, 0)` | | C++20 `[[likely]]` / `[[unlikely]]` | ✅ 语义等价且更现代 | 推荐新项目使用 | | 普通 `if` | ✅ 功能等价 ❌ 无优化提示 | 缺少编译器优化线索 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值