zoukankan      html  css  js  c++  java
  • Linux 内核中 likely 与 unlikely 的宏定义解析

    在 2.6 内核中,随处能够见到 likely() 和 unlikely() 的身影,那么为什么要用它们?它们之间有什么差别?

    首先要明白:

         if(likely(value)) 等价于 if(value)
    
         if(unlikely(value)) 也等价于 if(value)
    

    也就是说 likely() 和 unlikely() 从阅读和理解代码的角度来看。是一样的!。!

    #define likely(x)       __builtin_expect((x),1)
    #define unlikely(x)     __builtin_expect((x),0)

    __builtin_expect() 是 GCC (version >= 2.96)提供给程序猿使用的,目的是将“分支转移”的信息提供给编译器,这样编译器能够对代码进行优化。以降低指令跳转带来的性能下降。

    __builtin_expect((x),1) 表示 x 的值为真的可能性更大;
    __builtin_expect((x),0) 表示 x 的值为假的可能性更大。

    也就是说,使用 likely() ,运行 if 后面的语句 的机会更大,使用unlikely(),运行else 后面的语句的机会更大。
    比如以下这段代码,作者就觉得 prev 不等于 next 的可能性更大,

    if (likely(prev != next)) {
           next->timestamp = now;
            ...
    } else {
            ...;
     }

    通过这样的方式,编译器在编译过程中,会将可能性更大的代码紧跟着起面的代码,从而降低指令跳转带来的性能上的下降。

    另外内核2.6.31.5中likely和unlikely另一种定义:
    # ifndef likely
    # define likely(x) (__builtin_constant_p(x) ?

    !!(x) : __branch_check__(x, 1)) # endif # ifndef unlikely # define unlikely(x) (__builtin_constant_p(x) ?

    !!(x) : __branch_check__(x, 0)) # endif

    举个样例(内核版本号2.6.22.6):/kernel/shed.c中有一段:

    if (likely(!active_balance)) {
    /* We were unbalanced, so reset the balancing interval */
    sd->balance_interval = sd->min_interval;
    } else {
    /*
    * If we've begun active balancing, start to back off. This
    * case may not be covered by the all_pinned logic if there
    * is only 1 task on the busy runqueue (because we don't call
    * move_tasks).
    */
    if (sd->balance_interval max_interval)
    sd->balance_interval *= 2;
    }

    编译过程中,会将if后面{}里的内容编译到前面。else 后面{}里的内容编译到后面。若将likely换成unlikely 则正好相反。

    总之,likely与unlikely互换或不用都不会影响程序的正确性。

    但可能会影响程序的效率。

  • 相关阅读:
    hoj 1061 排列树问题
    [译稿]Google的9条创新原则(转)
    vs2008 Sys未定义比较完整的解决方案
    js右下角升起小窗口脚本示例
    扩展了flash8里array的方法
    js 滚动、切换代码的搜集
    prototype 1.3.1 跟 ajax冲突!!!莫名其妙!
    用AS删除Flash中输入文本开始和结尾的空格【转载】
    Flash右键触发与屏蔽
    实现Flash跨域访问
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7338034.html
Copyright © 2011-2022 走看看