環境:Mac Pro (i7 2.3GHz)、GCC 4.9、-O0(關閉優化)。測試 1 億次迴圈,每迴圈 10 次 if-else,比較條件為真與為假時的執行時間。
b<0,b=-1)int main() {
int n=100000000, b=-1;
while (n--) {
if (b<0) b--; else b--;
if (b<0) b--; else b--;
// 重複 10 次
}
return 0;
}
b>0,b=-1)int main() {
int n=100000000, b=-1;
while (n--) {
if (b>0) b--; else b--;
if (b>0) b--; else b--;
// 重複 10 次
}
return 0;
}
兩版本彙編幾乎相同,差別僅在條件跳轉指令:
jns (Jump if Not Sign / SF=0) → 條件真時跳過 else。jle (Jump if Less or Equal) → 條件假時跳過 if 體。其餘指令(subl、jmp、迴圈控制)完全一致。
代碼 1 (條件真) 耗時:約 2.31 秒 代碼 2 (條件假) 耗時:約 2.18 秒

-O0 下,編譯器生成「條件成立執行 if 體、不成立跳過」的直線碼。條件為假時直接落入 else 體(連續指令),無額外跳轉;條件為真需跳過 else 體,多一條跳轉指令。-O2/-O3,編譯器會將重複常數條件優化掉(死碼消除),兩版本皆極快。實際專案中分支預測器能極精準預測固定模式,差異可忽略。__builtin_expect 提示分支預測if (__builtin_expect(condition, 1)) { /* likely */ }
else { /* unlikely */ }
編譯器會將 likely 路徑安排為直線碼,unlikely 路徑放在冷碼區。