Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15361049
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2008-10-09 15:51:48

浅析linux中unlikely即__builtin_expect编译宏的实际意义所在

luther@gliethttp:~$ man gcc 可以查看-fno-builtin-function
luther@gliethttp:~$ gcc -g builtin_expect_func.c
luther@gliethttp:~$ ./a.out
else
if
if
else
if
if
所以这里可以看到if(__builtin_expect(cmd, 0))在逻辑上等效if(cmd).
luther@gliethttp:~$ objdump -DS a.out |tee luther.c 或者使用gdb或insight调试
...
08048406 <builtin_expect_func1>:

char* builtin_expect_func1(int cmd)
{
 8048406: 55 push %ebp
 8048407: 89 e5 mov %esp,%ebp
 8048409: 83 ec 04 sub $0x4,%esp
    if(__builtin_expect(cmd, 0)) {
 804840c: 8b 45 08 mov 0x8(%ebp),%eax
 804840f: 85 c0 test %eax,%eax
 8048411: 74 09 je 804841c <builtin_expect_func1+0x16>
        return "if";
 8048413: c7 45 fc 10 85 04 08 movl $0x8048510,-0x4(%ebp)
 804841a: eb 07 jmp 8048423 <builtin_expect_func1+0x1d>
    } else {
        return "else";
 804841c: c7 45 fc 13 85 04 08 movl $0x8048513,-0x4(%ebp)
 8048423: 8b 45 fc mov -0x4(%ebp),%eax
    }
}
 8048426: c9 leave
 8048427: c3 ret

08048428 <builtin_expect_func2>:

char* builtin_expect_func2(int cmd)
{
 8048428: 55 push %ebp
 8048429: 89 e5 mov %esp,%ebp
 804842b: 83 ec 04 sub $0x4,%esp
    if(__builtin_expect(cmd, 1)) {
 804842e: 8b 45 08 mov 0x8(%ebp),%eax
 8048431: 85 c0 test %eax,%eax
 8048433: 74 09 je 804843e <builtin_expect_func2+0x16>
        return "if";
 8048435: c7 45 fc 10 85 04 08 movl $0x8048510,-0x4(%ebp)
 804843c: eb 07 jmp 8048445 <builtin_expect_func2+0x1d>
    } else {
        return "else";
 804843e: c7 45 fc 13 85 04 08 movl $0x8048513,-0x4(%ebp)
 8048445: 8b 45 fc mov -0x4(%ebp),%eax
    }
}
 8048448: c9 leave
 8048449: c3 ret
...
可以看到并没有什么影响,与直接使用if(cmd)没有任何区别
luther@gliethttp:~$ man gcc 可以查看-fno-builtin-function
luther@gliethttp:~$ gcc -g -O2 builtin_expect_func.c 进行-O2优化或者-O3优化
luther@gliethttp:~$ ./a.out
else
if
if
else
if
if
所以这里可以看到在-O2最大优化,if(__builtin_expect(cmd, 0))在逻辑上仍等效if(cmd).
luther@gliethttp:~$ objdump -DS a.out |tee luther.c 或者使用gdb或insight调试
...

char* builtin_expect_func2(int cmd)
{
 8048380: 55 push %ebp
    if(__builtin_expect(cmd, 1)) {
 8048381: b8 20 85 04 08 mov $0x8048520,%eax
        return "else";
    }
}

char* builtin_expect_func2(int cmd)
{
 8048386: 89 e5 mov %esp,%ebp
    if(__builtin_expect(cmd, 1)) {
 8048388: 8b 55 08 mov 0x8(%ebp),%edx
 804838b: 85 d2 test %edx,%edx
 804838d: 74 02 je 8048391 <builtin_expect_func2+0x11> //可以看到这里跳转为je表示等于0的话跳,所以优先考虑1-if,这样可以减少一个跳转指令的执行,,如果cmd等于1的几率非常高,那么可以很好的完成优化,减少很多跳转[luther.gliethttp]
        return "if";
    } else {
        return "else";
    }
}
 804838f: 5d pop %ebp
 8048390: c3 ret
 8048391: 5d pop %ebp
    }
}

char* builtin_expect_func2(int cmd)
{
    if(__builtin_expect(cmd, 1)) {
 8048392: b8 23 85 04 08 mov $0x8048523,%eax
        return "if";
    } else {
        return "else";
    }
}
 8048397: c3 ret
 8048398: 90 nop
 8048399: 8d b4 26 00 00 00 00 lea 0x0(%esi),%esi

080483a0 <builtin_expect_func1>:
    printf("%s\n",builtin_expect_func2(2));

}

char* builtin_expect_func1(int cmd)
{
 80483a0: 55 push %ebp
    if(__builtin_expect(cmd, 0)) {
 80483a1: b8 20 85 04 08 mov $0x8048520,%eax
    printf("%s\n",builtin_expect_func2(2));

}

char* builtin_expect_func1(int cmd)
{
 80483a6: 89 e5 mov %esp,%ebp
    if(__builtin_expect(cmd, 0)) {
 80483a8: 8b 4d 08 mov 0x8(%ebp),%ecx
 80483ab: 85 c9 test %ecx,%ecx
 80483ad: 75 05 jne 80483b4 <builtin_expect_func1+0x14>//可以看到这里跳转为jne,非0,所以优先考虑0-if,这样可以减少一个跳转指令的执行,如果cmd等于0的几率非常高,那么可以很好的完成优化,减少很多跳转[luther.gliethttp]
 80483af: b8 23 85 04 08 mov $0x8048523,%eax
        return "if";
    } else {
        return "else";
    }
}
 80483b4: 5d pop %ebp
 80483b5: c3 ret
...

测试源码:
#include <stdio.h>

char* builtin_expect_func1(int cmd);
char* builtin_expect_func2(int cmd);
int main(int argc, char *argv[])
{
    printf("%s\n",builtin_expect_func1(0));
    printf("%s\n",builtin_expect_func1(1));
    printf("%s\n",builtin_expect_func1(2));

    printf("%s\n",builtin_expect_func2(0));
    printf("%s\n",builtin_expect_func2(1));
    printf("%s\n",builtin_expect_func2(2));

}

char* builtin_expect_func1(int cmd)
{
    if(__builtin_expect(cmd, 0)) {
        return "if";
    } else {
        return "else";
    }
}

char* builtin_expect_func2(int cmd)
{
    if(__builtin_expect(cmd, 1)) {
        return "if";
    } else {
        return "else";
    }
}

阅读(2668) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~