嵌套逻辑中如何放置likely/unlikely语句以优化代码性能?
嵌套逻辑下likely/unlikely宏的性能优化问题
像Linux内核、DPDK这类对性能极度敏感的软件,会用C语言的likely()/unlikely()宏给编译器传递分支概率信息,辅助做分支预测优化。下面结合一段代码示例(已知a > b是极低概率的罕见场景),聊聊嵌套逻辑里这两个宏的最优用法。
示例代码
bool foo() { foo1(1); foo2(2); /* if (unlikely(a > b)) */ /* if (a > b)*/ { puts("Ohhh!!! Rare case"); return true; } return false; } int main(void) { /* if (unlikely(foo())) */ /* if (foo()) */ { puts("Azaza"); } }
三种可选优化方案
方案1
if (unlikely(a > b)) ... if (unlikely(foo()))
方案2
if (a > b) ... if (unlikely(foo()))
方案3
if (unlikely(a > b)) ... if (foo())
最优方案分析
方案1理论上效率最高,原因很直接:
- 已知
a > b是罕见事件,那foo()返回true的概率和a > b的概率完全一致——同样极低。 - 在
foo()内部给a > b加unlikely():编译器会把这个罕见分支的代码(puts和return true)放到指令流的“冷区”,让大概率走的return false路径指令更连续,既减少指令缓存miss的概率,也能帮硬件分支预测器更精准地预判这个分支不会执行。 - 在
main()里给foo()加unlikely():因为foo()返回true是极低概率事件,编译器会把puts("Azaza")的代码也放到冷区,让main()的主流路径(不执行该分支)的指令流更顺畅,避免分支预测失误带来的性能损耗。 - 这两处优化是互补不冲突的:一个优化函数内的局部分支,一个优化跨函数的分支判断,结合起来能把分支预测的准确性和指令缓存的利用率拉到最高。
内容的提问来源于stack exchange,提问作者NK-cell
相关产品推荐
相关产品推荐

