likely和unlikely

本文发布时间: 2019-Mar-22
在内核中我们经常遇到likely和unlikely,特别是在出错函数中,那么引入这两个宏有什么作用呢?下面是我在内核include/linux/compiler.h中找到的:#define likely(x) __builtin_expect(!!(x), 1)#define unlikely(x) __builtin_expect(!!(x), 0) 上述代码的__builtin_expect是GCC提供给程序员使用的,目的是将“分支转移的信息提供给编译器,这样编译器可以对代码进行优化,以减少指令调转带来的性能下降。下面是GCC上__builtin_expect的解释:- Built-in Function: long __builtin_expect (long EXP, long C) You may use `__builtin_expect' to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (`-fprofile-arcs'), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect. The return value is the value of EXP, which should be an integral expression. The value of C must be a compile-time constant. The semantics of the built-in are that it is expected that EXP == C. For example: if (__builtin_expect (x, 0)) foo (); would indicate that we do not expect to call `foo', since we expect `x' to be zero. Since you are limited to integral expressions for EXP, you should use constructions such as if (__builtin_expect (ptr != NULL, 1)) error (); when testing pointer or floating-point values.__builtin_expect(!!(x), 1)表示x为真的可能性大一些。也就是if后面的语句可能性大一些。__builtin_expect(!!(x), 1)表示x为假的可能性大一些。也就是else后面的语句可能性大一些。还是用具体的例子解释会更清楚一些:下面是我在shell底下写的一个C程序:lwp@lwp-linux:~/kernel$ cat test2.c#define LIKELY(x) __builtin_expect(!!(x), 1)#define UNLIKELY(x) __builtin_expect(!!(x), 0)int test_likely(int x){if(LIKELY(x)){ x = 5;}else{ x = 6;}return x;}int test_unlikely(int x){if(UNLIKELY(x)){ x = 5;}else{ x = 6;}return x;}在终端下敲入以下命令:lwp@lwp-linux:~/kernel$ gcc -fprofile-arcs -O2 -c test2.clwp@lwp-linux:~/kernel$ objdump -d test2.o可以得到如下结果:test2.o: file format elf32-i386Disassembly of section .text:00000000 <test_likely>:0: 83 ec 04 sub $0x4,%esp3: 8b 44 24 08 mov 0x8(%esp),%eax7: 83 05 10 00 00 00 01 addl $0x1,0x10e: 83 15 14 00 00 00 00 adcl $0x0,0x1415: 85 c0 test %eax,%eax17: 74 09 je 22 <test_likely+0x22>19: b8 05 00 00 00 mov $0x5,%eax1e: 83 c4 04 add $0x4,%esp21: c3 ret22: 83 05 18 00 00 00 01 addl $0x1,0x1829: b8 06 00 00 00 mov $0x6,%eax2e: 83 15 1c 00 00 00 00 adcl $0x0,0x1c35: eb e7 jmp 1e <test_likely+0x1e>37: 89 f6 mov %esi,%esi39: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi00000040 <test_unlikely>:40: 83 ec 04 sub $0x4,%esp43: 8b 54 24 08 mov 0x8(%esp),%edx47: 83 05 00 00 00 00 01 addl $0x1,0x04e: 83 15 04 00 00 00 00 adcl $0x0,0x455: 85 d2 test %edx,%edx57: 75 17 jne 70 <test_unlikely+0x30>59: 83 05 08 00 00 00 01 addl $0x1,0x860: b8 06 00 00 00 mov $0x6,%eax65: 83 15 0c 00 00 00 00 adcl $0x0,0xc6c: 83 c4 04 add $0x4,%esp6f: c3 ret70: b8 05 00 00 00 mov $0x5,%eax75: eb f5 jmp 6c <test_unlikely+0x2c>Disassembly of section .text.startup:00000000 <_GLOBAL__sub_I_65535_0_test_likely>:0: 83 ec 1c sub $0x1c,%esp3: c7 04 24 00 00 00 00 movl $0x0,(%esp)a: e8 fc ff ff ff call b <_GLOBAL__sub_I_65535_0_test_likely+0xb>f: 83 c4 1c add $0x1c,%esp12: c3 ret 总的来说,这两个宏对程序的结果没有影响,使用它只是提高了程序的效率。我们只有在你已经对可能发生的结果有很大的预算的时候使用它。


(以上内容不代表本站观点。)
---------------------------------
本网站以及域名有仲裁协议。
本網站以及域名有仲裁協議。

2024-Mar-04 02:11pm
栏目列表