在线时间1080 小时
UID299704
注册时间2011-6-18
NXP金币2022
TA的每日心情 | 开心 2025-8-8 16:43 |
---|
签到天数: 1504 天 连续签到: 1 天 [LV.Master]伴坛终老
版主
  
- 积分
- 10093
- 最后登录
- 2025-8-8
|
在阅读内核的时候经常会遇到下面的代码:
- *n_mask_hit = 0;
- if (unlikely(!skb_hash)) {
- u32 mask_index = 0;
- return flow_lookup(tbl, ti, ma, key, n_mask_hit, &mask_index);
- }
复制代码 likely()和unlikely()的宏定义在 #include <linux/compiler.h>
- #define likely(x) __builtin_expect(!!(x), 1)
- #define unlikely(x) __builtin_expect(!!(x), 0)
复制代码 宏定义里面的__builtin_expect()为GCC的内建函数。
该函数用来引导gcc进行条件分支预测。在一条指令执行时,由于流水线的作用,CPU可以同时完成下一条指令的取指,这样可以提高CPU的利用率。在执行条件分支指令时,CPU也会预取下一条执行,但是如果条件分支的结果为跳转到了其他指令,那CPU预取的下一条指令就没用了,这样就降低了流水线的效率。
另外,跳转指令相对于顺序执行的指令会多消耗CPU时间,如果可以尽可能不执行跳转,也可以提高CPU性能。
使用__builtin_expect (long exp, long c)函数可以帮助gcc优化程序编译后的指令序列,使汇编指令尽可能的顺序执行,从而提高CPU预取指令的正确率和执行效率。
__builtin_expect(exp, c)接受两个long型的参数,用来告诉gcc:exp==c的可能性比较大。
例如,__builtin_expect(exp, 1) 表示程序执行过程中,exp取到1的可能性比较大。该函数的返回值为exp自身。
通过__builtin_expect() 函数的作用,我们可以得出它们的作用:
- likely(x)等价于x,即if(likely(x))等价于if(x),但是它告诉gcc,x取1的可能性比较大
- unlikely(x)等价于x,即if(unlikely(x))等价于if(x),但是它告诉gcc,x取0的可能性比较大
如果我们编写示例代码,并反编译到汇编代码,就可以发现
从汇编代码中可以看出,如果else成立,即x==0,则第一条跳转指令不成功,指令得以顺序执行。 而如果if成立,则需要多执行一次跳转。 什么时候使用这两个宏呢?
You should use it only in cases when the likeliest branch is very very very likely, or when the unlikeliest branch is very very very unlikely. 既然是GCC级别的优化,那么一定是超级多的情况下才使用。
参考链接:
|
|