详解likely和unlikely函数
内核源码:linux-2.6.38.8.tar.bz2
参考文档:http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Other-Builtins.html#Other-Builtins
在Linux内核中likely和unlikely函数有两种(只能两者选一)实现方式,它们的实现原理稍有不同,但作用是相同的,下面将结合linux-2.6.38.8版本的内核代码来进行讲解。
1、对__builtin_expect的封装
它们的源代码如下:
/* linux-2.6.38.8/include/linux/compiler.h */
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
__builtin_expect 是GCC的内置函数,用来对选择语句的判断条件进行优化,常用于一个判断条件经常成立(如likely)或经常不成立(如unlikely)的情况。
__builtin_expect的函数原型为long __builtin_expect (long exp, long c),返回值为完整表达式exp的值,它的作用是期望表达式exp的值等于c(注意,如果exp == c条件成立的机会占绝大多数,那么性能将会得到提升,否则性能反而会下降)。
在普通的应用程序中也可以使用__builtin_expect,如下面的例子:
#include <stdio.h>int main(void)
{int a;scanf("%d", &a);if(__builtin_expect(a, 4))printf("if: a = %d\n", a);elseprintf("else: a = %d\n", a);return 0;
}
分别输入整数0到4来进行5次测试,它们的输出分别为:
else: a = 0if: a = 1if: a = 2if: a = 3if: a = 4
注意,在上例中只有输入整数0的时候才执行else后的打印语句,也就是说__builtin_expect(a, 4)函数的值就是表达式a的值。
记住,它们只是用来提升性能的优化手段,并不会改变原来表达式的值。
2、使用__branch_check__函数
它们的源代码如下:
/* linux-2.6.38.8/include/linux/compiler.h */
# 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
(1)、先使用内置函数__builtin_constant_p忽略表达式x为常量的情况
__builtin_constant_p也是GCC的内置函数,函数原型为int __builtin_constant_p(exp),用于判断表达式exp在编译时是否是一个常量,如果是则函数的值为整数1,否则为0,如下面的例子:
#include <stdio.h>
#include <stdlib.h>#define VALUE 5int main(void)
{char *ptr = NULL;int num, count;ptr = malloc(20);num = __builtin_constant_p(ptr) ? 20 : 20 + 10;printf("num = %d\n", num);free(ptr);count = __builtin_constant_p(VALUE) ? 20 + VALUE : 10;printf("count = %d\n", count);return 0;
}
例子的输出结果:
num = 30
count = 25
例子中的ptr为指针变量,所以__builtin_constant_p(ptr)的值为0,num的值为30。
(2)、函数__branch_check__的实现
/* linux-2.6.38.8/include/linux/compiler.h */
#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; \})
使用它来检查判断条件并记录likely判断的预测信息,之后根据预测信息进行相应的优化以提升性能。
函数__branch_check__的返回值为______r的值,也就是参数x的值。
详解likely和unlikely函数相关推荐
- python open 打开是什么类型的文件-详解Python中open()函数指定文件打开方式的用法...
文件打开方式 当我们用open()函数去打开文件的时候,有好几种打开的模式. 'r'->只读 'w'->只写,文件已存在则清空,不存在则创建. 'a'->追加,写到文件末尾 'b'- ...
- php打印出函数的内容吗,PHP打印函数集合详解以及PHP打印函数对比详解(精)
1 echo();2 print();3 die();4 printf();5 sprintf();6 print_r();7 var_dump(); 1 echo() 可以同时输出多个字符串,可以多 ...
- python中groupby()函数讲解与示例_详解python中groupby函数通俗易懂
一.groupby 能做什么? python中groupby函数主要的作用是进行数据的分组以及分组后地组内运算! 对于数据的分组和分组运算主要是指groupby函数的应用,具体函数的规则如下: df[ ...
- python函数的使用场景_详解python中strip函数的使用场景
python strip()函数 介绍,需要的朋友可以参考一下 函数原型 声明:s为字符串,rm为要删除的字符序列 s.strip(rm) 删除s字符串中开头.结尾处,位于 rm删除序列的字符 s.l ...
- python中get函数是什么意思_详解python中get函数的用法(附代码)_后端开发
strncmp函数用法详解_后端开发 strncmp函数为字符串比较函数,其函数语法为"int strncmp ( const char * str1, const char * str2, ...
- 详解c语言main函数、printf函数、scanf函数与va家族
C语言入门与提升(1)--详解c语言main函数.printf函数与scanf函数,与va家族 前言: 为什么要学习C语言呢?C语言作为最古老的语言之一,走过了半个多世纪的风风雨雨,至今仍然长盛不衰, ...
- php simplexml_load_file 详解,php中simplexml_load_file函数用法实例讲解
php中simplexml_load_file函数用法实例讲解 发布于 2015-02-07 06:53:40 | 136 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文 ...
- C语言return的用法详解,C语言函数返回值详解。 (本次转载仅供学习,感谢原创!!转发自C语言中文网,如有侵权请私信本人删除)
C语言return的用法详解,C语言函数返回值详解 转载:http://c.biancheng.net/view/1855.html 函数的返回值是指函数被调用之后,执行函数体中的代码所得到的结果,这 ...
- oracle 总转横函数,详解Oracle行列转换函数-pivot函数和unpivot函数-多智时代
今天主要介绍一下Oracle行转列及列转行常见函数,下面一起来看看吧! 行列转换 pivot函数:行转列函数 语法:pivot(任一聚合函数 for 需专列的值所在列名 in (需转为列名的值)): ...
- c语言getline函数什么意思,详解C++ cin.getline函数
cin 虽然可以使用 cin 和 >> 运算符来输入字符串,但它可能会导致一些需要注意的问题. 当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格.制表符或换行符).一旦它接 ...
最新文章
- 为什么华为在发布会不提鸿蒙,华为又要开发布会?这次没有手机,鸿蒙系统要当主角!...
- forward 和redirect的区别
- Java 14:查看更新的switch语句
- 36 SD配置-销售凭证设置-定义项目类别
- 数据库周刊第十七期来啦!
- python显示邮件发送成功失败_python stmp module 163邮箱发送邮件不成功
- (转)Java DecimalFormat 用法(数字格式化)
- c语言头文件 数学函数,头文件cmath中常用函数
- webservice 调用错误
- IBM的人工智能“沃森”首次确诊罕见白血病,只用了10分钟!
- git untracked working tree files would be overwritten by merge
- echarts 迁徙图
- 病毒分析 - 特征码提取
- 关于微信的几点更新与操作
- ONF推新版Atrium 获得OpenDaylight支持
- 程序员去哪接私活?分享10个兼职平台,人已赚麻
- 动态规划:奶牛吃草问题
- 办公技巧——PPT添加页码
- 安卓系统双屏异显_双屏异显在Android系统上的实现
- Vue 使用 yarn 报错