Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android 本地代碼中的LIKELY和UNLIKELY宏

Android 本地代碼中的LIKELY和UNLIKELY宏

編輯:Android開發實例

閱讀Android Frameworks中的C++代碼時,經常會碰到在條件判斷語句中使用了LIKELY和UNLIKELY這兩個宏,找到這兩個宏的定義如下:

 

 

  1. #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))  
  2. #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))  

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

你可以使用__builtin_expect給編譯器提供分支預測的信息,通常,你因該明確使用這個編譯選項(‘-fprofile-arcs’),因為很多程序員在如何預測他們編寫的代碼實際如何執行方面都很糟糕,使用這個宏可以很方面地讓編譯器優化分支跳轉的代碼。

這個函數的返回值就是exp:一個整形表達式,c必須是一個常量,該內建函數從語義上是表明:我們期望exp == c。

所以,如果你不考慮程序執行的效率,加不加LIKELY和UNLIKELY宏,執行的結果是一樣的:

 

 

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

 

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

 

執行的結果是一樣的。

那為什麼還要使用這兩個宏定義? 以汽車的速度為例子,如果速度超過200公裡/小時表示有異常發生,代碼可以這樣寫:

 

  1. if(speed >= 200){  
  2.     //異常處理代碼  
  3.     .....  
  4.     stop();  
  5. }else{  
  6.     //正常處理代碼  
  7.     continue();  
 

 

也可以這樣寫:

 

 

 

這兩個方案執行後都是正確的,但是顯然效率是不一樣的,因為大多數情況下,汽車的速度不會超過200公裡/小時,當采用第一個方案時,大多數情況下,代碼執行到這裡時CPU都要執行分支跳轉的操作,這破壞了CPU的指令執行流水線,對性能的影響是顯而易見的。而第二個方案則避免了這一問題,因為大多數時候都是順序執行的。

對於第一種方案,我們可以加上UNLIKELY宏來讓編譯器來優化:

 

  1. if(UNLIKELY(speed >= 200)){  
  2.     //異常處理代碼  
  3.     .....  
  4.     stop();  
  5. }else{  
  6.     //正常處理代碼  
  7.     continue();  
 

 

加上UNLIKELY宏後,相當於告訴編譯器:速度大於200是很少出現的。這樣編譯器在編譯代碼時,會適當地調整條件判斷的方式,讓CPU的指令執行順序盡可能不被打亂,已達到優化性能的效果。

所以,對於第二種方案,我們同樣可以加上LIKELY宏:

 

 
  1. if(LIKELY(speed < 200)){     
  2.     //正常處理代碼     
  3.     continue();     
  4. }else{     
  5.     //異常處理代碼     
  6.     .....     
  7.     stop();     
  8. }    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved