likelyとunlikely
likelyは条件が通常は真で、unlikelyは条件が通常は偽であるケースで、if文のパフォーマンス向上のために使用します。これらのマクロは、__builtin_expectで実装されgccマターとなります。
次実行コードのインストラクションポインタIPをインクリメントするのでなく、jmpは次実行コードをキャッシュメモリから取得し、それをipに設定する負荷のかかる仕組みが必要と、CPUマターであるにしても想像できます。
gcc依存と思いますが、私の環境では、最適化オプションO2以降でないと__builtin_expectが有効となりませんでした。
カーネル3ではgccの変更にともない、カーネルオプションにより、__builtin_expect以外による展開がされるようになっています。
# define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0)__builtin_expectは第1引数が第二引数1(真)なら、else処理はjmpとし、第1引数が0(偽)なら、then処理がjmpする様に展開されます。
次実行コードのインストラクションポインタIPをインクリメントするのでなく、jmpは次実行コードをキャッシュメモリから取得し、それをipに設定する負荷のかかる仕組みが必要と、CPUマターであるにしても想像できます。
void likely(int a) { if (__builtin_expect(!!(a == 2), 1)) { printf("%d\n", a); } } void unlikely(int a) { if (__builtin_expect(!!(a == 2), 0)) { printf("%d\n", a); } }
likely: .LFB13: .cfi_startproc subl $28, %esp .cfi_def_cfa_offset 32 cmpl $2, 32(%esp) jne .L5 <- elseはjmp .L5 movl $2, 4(%esp) movl $.LC0, (%esp) call printf .L5: addl $28, %esp .cfi_def_cfa_offset 4 ret unlikely: .LFB14: .cfi_startproc subl $28, %esp .cfi_def_cfa_offset 32 cmpl $2, 32(%esp) je .L9 <- thenはjmp .L9 .L7: addl $28, %esp .cfi_remember_state .cfi_def_cfa_offset 4 ret .L9: .cfi_restore_state movl $2, 4(%esp) movl $.LC0, (%esp) call printf jmp .L7 ***追記__builtin_expect(!!(x), 1)で、!!(x)とするのは、ポインタとする変数がNULLかそうでないか等のケースを想定しての実装です。なお、(a == 2)等の真偽を問うケースでは、!!は無視されます。
gcc依存と思いますが、私の環境では、最適化オプションO2以降でないと__builtin_expectが有効となりませんでした。
カーネル3ではgccの変更にともない、カーネルオプションにより、__builtin_expect以外による展開がされるようになっています。