__builtin_expect详解

__builtin_expect详解在 GTK 2 0 源码中有很多这样的宏 G LIKELY 和 G UNLIKELY 比如下面这段代码 if G LIKELY acat 1 nbsp nbsp nbsp nbsp allocatethro nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp ThreadMemory tmem thread memory from self nbsp nbsp nbsp nbsp nbsp guintix

在GTK+2.0源码中有很多这样的宏:G_LIKELY和G_UNLIKELY。比如下面这段代码:

if (G_LIKELY (acat == 1))     /* allocate through magazine layer */
    {
      ThreadMemory *tmem = thread_memory_from_self();
      guint ix = SLAB_INDEX (allocator, chunk_size);
      if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))
        {
          thread_memory_swap_magazines (tmem, ix);
          if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))
            thread_memory_magazine1_reload (tmem, ix);
        }
      mem = thread_memory_magazine1_alloc (tmem, ix);
    }































在源码中,宏G_LIKELY和G_UNLIKELY 是这么定义的:

#define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 1))
#define G_UNLIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 0))

宏_G_BOOLEAN_EXPR的作用是把expr转换为0和1,即真假两种。要理解宏G_LIKELY和G_UNLIKELY ,很明显必须理解__builtin_expect。__builtin_expect是GCC(version>=2.9)引进的宏,其作用就是帮助编译器判断条件跳转的预期值,避免跳转造成时间乱费。拿上面的代码来说:

if (G_LIKELY (acat == 1))     //表示大多数情况下if里面是真,程序大多数直接执行if里面的程序

if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))//表示大多数情况if里面为假,程序大多数直接执行else里面的程序

可能大家看到还是一头雾水,看下面一段就会明白其中的乐趣啦;

//test_builtin_expect.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;
}





































[lammy@localhost test_builtin_expect]$ gcc -fprofile-arcs -O2 -c test_builtin_expect.c 
[lammy@localhost test_builtin_expect]$ objdump -d test_builtin_expect.o

test_builtin_expect.o:     file format elf32-i386

Disassembly of section .text:

00000000 
  
    : 
   
   0: 55                   push   %ebp
   1: 89 e5                mov    %esp,%ebp
   3: 8b 45 08             mov    0x8(%ebp),%eax
   6: 83 05 38 00 00 00 01 addl   $0x1,0x38
   d: 83 15 3c 00 00 00 00 adcl   $0x0,0x3c
14: 85 c0                test   %eax,%eax
16: 74 15                je     2d // 主要看这里
18: 83 05 40 00 00 00 01 addl   $0x1,0x40
1f: b8 05 00 00 00       mov    $0x5,%eax
24: 83 15 44 00 00 00 00 adcl   $0x0,0x44
2b: 5d                   pop    %ebp
2c: c3                   ret   
2d: 83 05 48 00 00 00 01 addl   $0x1,0x48
34: b8 06 00 00 00       mov    $0x6,%eax
39: 83 15 4c 00 00 00 00 adcl   $0x0,0x4c
40: 5d                   pop    %ebp
41: c3                   ret   
42: 8d b4 26 00 00 00 00 lea    0x0(%esi,%eiz,1),%esi
49: 8d bc 27 00 00 00 00 lea    0x0(%edi,%eiz,1),%edi
























































00000050 
  
    : 
   
50: 55                   push   %ebp
51: 89 e5                mov    %esp,%ebp
53: 8b 55 08             mov    0x8(%ebp),%edx
56: 83 05 20 00 00 00 01 addl   $0x1,0x20
5d: 83 15 24 00 00 00 00 adcl   $0x0,0x24
64: 85 d2                test   %edx,%edx
66: 75 15                jne    7d // 主要看这里
68: 83 05 30 00 00 00 01 addl   $0x1,0x30
6f: b8 06 00 00 00       mov    $0x6,%eax
74: 83 15 34 00 00 00 00 adcl   $0x0,0x34
7b: 5d                   pop    %ebp
7c: c3                   ret   
7d: 83 05 28 00 00 00 01 addl   $0x1,0x28
84: b8 05 00 00 00       mov    $0x5,%eax
89: 83 15 2c 00 00 00 00 adcl   $0x0,0x2c
90: 5d                   pop    %ebp
91: c3                   ret   
92: 8d b4 26 00 00 00 00 lea    0x0(%esi,%eiz,1),%esi
99: 8d bc 27 00 00 00 00 lea    0x0(%edi,%eiz,1),%edi





















































000000a0 <_GLOBAL__I_65535_0_test_likely>:
a0: 55                   push   %ebp
a1: 89 e5                mov    %esp,%ebp
a3: 83 ec 08             sub    $0x8,%esp
a6: c7 04 24 00 00 00 00 movl   $0x0,(%esp)
ad: e8 fc ff ff ff       call   ae <_GLOBAL__I_65535_0_test_likely+0xe>
b2: c9                   leave
b3: c3                   ret   
[lammy@localhost test_builtin_expect]$






















两个函数编译生成的汇编语句所使用到的跳转指令不一样,仔细分析下会发现__builtin_expect实际上是为了满足在大多数情况不执行跳转指令,所以__builtin_expect仅仅是告诉编译器优化,并没有改变其对真值的判断。

这种用法在linux内核中也经常用到,国外也有一篇相关的文章,大家不妨看看:http://kernelnewbies.org/FAQ/LikelyUnlikely

不知大家注意到没有,我在生产汇编时用的是gcc -fprofile-arcs -O2 -c test_builtin_expect.c,而不是gcc -O2 -c test_builtin_expect.c,具体可以参考http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/217596.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午9:13
下一篇 2026年3月18日 上午9:13


相关推荐

  • 内积空间

    内积空间目录一 线性空间二 度量空间三 赋范线性空间四 内积空间五 一个例子 RnR nRn 首先 介绍线性空间和度量空间 分别具有代数结构和拓扑结构 其次 介绍兼有两种结构的赋范线性空间 然后 介绍内积空间 作为赋范线性空间的特例 最后 给出一个例子 Rn smallR nRn 一 线性空间 什么是空间 Inmathematic aspaceisaset sometimes

    2026年3月26日
    2
  • dw中css制作导航,Dreamweaver导航条按钮制作方法

    dw中css制作导航,Dreamweaver导航条按钮制作方法核心提示:教你Dreamweaver用表格巧妙制作导航条按钮看到上面的导航条了吗?你可以点击一下看看它的效果,请注意,这可是用表格做出来的,你相信吗?其实代码很简单,现在让我们来看看该怎么做。1.首先创建一个1×6的表格,参数为:border=0cellspacing=3cellpadding=0;2.在这个表格的每个单元格内分别插入一个表格,宽度和高度设为100%;3.建立一个CSS样式.u…

    2022年7月22日
    13
  • oracle语句和mysql语句有什么不同_短语与句子的区别

    oracle语句和mysql语句有什么不同_短语与句子的区别Oracle与MySQL的SQL语句区别1数据库/*&amp;amp;nbsp;mysql可以创建数据库,而oracle没有这个操作,oracle只能创建实例;&amp;amp;nbsp;sql数据库操作:database&amp;amp;nbsp;格式:&amp;amp;nbsp;&amp;amp;nbsp;*createdatabase数

    2025年11月16日
    6
  • 安卓耳机接口(我读懂了你作文800字)

    一文读懂Android/iOS手机如何通过音频接口与外设通信0背景1音频口通信特点1.1通用性强1.2速率低1.3小信号2手机音频口通信原理2.1音频接口2.2音频通信模型与信号组成2.2.1通信模型2.2.2音频通信使用的信号3手机音频口全双工通信方案3.1设备→手机3.2手机→设备4案例分析(以2FSK

    2022年4月15日
    55
  • 剑指offer试题——替换空格

    剑指offer试题——替换空格

    2022年4月2日
    39
  • 离散傅里叶变换和离散时间傅里叶变换_离散傅里叶变换求相位

    离散傅里叶变换和离散时间傅里叶变换_离散傅里叶变换求相位1.离散时间傅里叶变换的导出针对离散时间非周期序列,为了建立它的傅里叶变换表示,我们将采用与连续情况下完全类似的步骤进行。考虑某一序列$x[n]$,它具有有限持续期;也就是说,对于某个整数$

    2022年8月4日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号