閱讀Android Frameworks中的C++代碼時,經常會碰到在條件判斷語句中使用了LIKELY和UNLIKELY這兩個宏,找到這兩個宏的定義如下:
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))<br />#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宏,執行的結果是一樣的:
if( LIKELY(exp) )<br /> {<br /> }<br /> else<br /> {<br /> }
和
- if
(exp)
- {
- }
- else
- {
- }
執行的結果是一樣的。
那為什麼還要使用這兩個宏定義? 以汽車的速度為例子,如果速度超過200公裡/小時表示有異常發生,代碼可以這樣寫:
- if
(speed >= 200){
- //異常處理代碼
- .....
- stop();
- }else
{
- //正常處理代碼
- continue
();
- }
也可以這樣寫:
- if
(speed < 200){
- //正常處理代碼
- continue
();
- }else
{
- //異常處理代碼
- .....
- stop();
- }
這兩個方案執行後都是正確的,但是顯然效率是不一樣的,因為大多數情況下,汽車的速度不會超過200公裡/小時,當採用第一個方案時,大多數情況
下,代碼執行到這裡時CPU都要執行分支跳轉的操作,這破壞了CPU的指令執行流水線,對效能的影響是顯而易見的。而第二個方案則避免了這一問題,因為大
多數時候都是順序執行的。
對於第一種方案,我們可以加上UNLIKELY宏來讓編譯器來最佳化:
- if
(UNLIKELY(speed >= 200)){
- //異常處理代碼
- .....
- stop();
- }else
{
- //正常處理代碼
- continue
();
- }
加上UNLIKELY宏後,相當於告訴編譯器:速度大於200是很少出現的。這樣編譯器在編譯代碼時,會適當地調整條件判斷的方式,讓CPU的指令執行順序儘可能不被打亂,已達到最佳化效能的效果。
所以,對於第二種方案,我們同樣可以加上LIKELY宏:
- if
(LIKELY(speed < 200)){
- //正常處理代碼
- continue
();
- }else
{
- //異常處理代碼
- .....
- stop();
- }
http://blog.csdn.net/DroidPhone/archive/2010/11/03/5984255.aspx