Android 本地代码中的LIKELY和UNLIKELY宏

阅读Android Frameworks中的C++代码时,经常会碰到在条件判断语句中使用了LIKELY和UNLIKELY这两个宏,找到这两个宏的定义如下:

long __builtin_expect (long exp, long c) 是GCC的内建函数,解析如下:

你可以使用__builtin_expect给编译器提供分支预测信息,通常,你应该明确使用这个编译选项(‘-fprofile-arcs’),因为很多程序员在如何预测他们编写的代码的实际如何执行方面都是很糟糕的,使用这个宏可以很方便地让编译器优化分支跳转的代码。

这个函数的返回值就是exp:一个整形表达式,c必须是一个常量,该内建函数从语义上是表明:我们期望exp == c。

所以,如果你不考虑程序执行的效率,加不加LIKELY和UNLIKELY宏,执行的结果是一样的:

  1. if
    (exp)  
  2. {  
  3. }  
  4. else
      
  5. {  
  6. }  

执行的结果是一样的。

那为什么还要使用这两个宏定义? 以汽车的速度为例子,如果速度超过200公里/小时表示有异常发生,代码可以这样写:

  1. if
    (speed >= 200){  
  2.     //异常处理代码
      
  3.     .....  
  4.     stop();  
  5. }else
    {  
  6.     //正常处理代码
      
  7.     continue
    ();  
  8. }  

也可以这样写:

  1. if
    (speed < 200){  
  2.     //正常处理代码
      
  3.     continue
    ();  
  4. }else
    {  
  5.     //异常处理代码
      
  6.     .....  
  7.     stop();  
  8. }  

这两个方案执行后都是正确的,但是显然效率是不一样的,因为大多数情况下,汽车的速度不会超过200公里/小时,当采用第一个方案时,大多数情况
下,代码执行到这里时CPU都要执行分支跳转的操作,这破坏了CPU的指令执行流水线,对性能的影响是显而易见的。而第二个方案则避免了这一问题,因为大
多数时候都是顺序执行的。

对于第一种方案,我们可以加上UNLIKELY宏来让编译器来优化:

  1. if
    (UNLIKELY(speed >= 200)){  
  2.     //异常处理代码
      
  3.     .....  
  4.     stop();  
  5. }else
    {  
  6.     //正常处理代码
      
  7.     continue
    ();  
  8. }  

加上UNLIKELY宏后,相当于告诉编译器:速度大于200是很少出现的。这样编译器在编译代码时,会适当地调整条件判断的方式,让CPU的指令执行顺序尽可能不被打乱,已达到优化性能的效果。

所以,对于第二种方案,我们同样可以加上LIKELY宏:

  1. if
    (LIKELY(speed < 200)){  
  2.     //正常处理代码
      
  3.     continue
    ();  
  4. }else
    {  
  5.     //异常处理代码
      
  6.     .....  
  7.     stop();  

 

http://blog.csdn.net/DroidPhone/archive/2010/11/03/5984255.aspx

原文链接: https://www.cnblogs.com/eustoma/archive/2011/06/19/2415836.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    Android 本地代码中的LIKELY和UNLIKELY宏

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/27420

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午5:01
下一篇 2023年2月8日 上午5:02

相关推荐