커널에서 사용되는 매크로로 다음과 같다.
include/linux/compiler.h
#define likely(x) __builtin_expect((x),1) #define unlikely(x) __builtin_expect((x),0)
- likely()는 true가 될 확률이 높은 조건문에서 사용하여 성능을 높이고자 사용한다.
- unlikely()는 false가 될 확률이 높은 조건문에서 사용하여 성능을 높이고자 사용한다.
__builtin_expect()
Built-in Function: long __builtin_expect (long exp, long c)
- gcc 내장 함수로서 컴파일러에게 branch prediction 정보를 주고자하는 함수이다.
- 자주 사용되지 않는 문장을 함수의 뒷 부분에 배치하여 메모리 캐시나 brach prediction cache에 영향을 주어 성능을 최적화 시키려할 때 사용한다.
- likely/unlikely와 다르게 userspace에서도 사용할 수 있다.
디버그 추적용
디버그 추적 옵션이 동작하는 경우 사용되는 likely() 및 unlikely() 매크로의 소스는 다음과 같다.
include/linux/compiler.h
#if defined(CONFIG_TRACE_BRANCH_PROFILING) \ && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__) void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #define likely_notrace(x) __builtin_expect(!!(x), 1) #define unlikely_notrace(x) __builtin_expect(!!(x), 0) #define __branch_check__(x, expect) ({ \ int ______r; \ static struct ftrace_branch_data \ __attribute__((__aligned__(4))) \ __attribute__((section("_ftrace_annotated_branch"))) \ ______f = { \ .func = __func__, \ .file = __FILE__, \ .line = __LINE__, \ }; \ ______r = likely_notrace(x); \ ftrace_likely_update(&______f, ______r, expect); \ ______r; \ }) /* * Using __builtin_constant_p(x) to ignore cases where the return * value is always the same. This idea is taken from a similar patch * written by Daniel Walker. */ # ifndef likely # define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1)) # endif # ifndef unlikely # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) # endif
__builtin_constant_p()
__builtin_constant_p는 인수가 컴파일 시 상수로 알려져 있으면 정수 1을 반환하고 그렇지 않으면 0을 반환합니다.
참고
- likely()/unlikely() macros in the Linux kernel – how do they work? What’s their benefit? | stackoverflow.com
- likely, unlikely 함수란? | morenice