详解likely和unlikely函数【转】
本文转载自:http://blog.csdn.net/npy_lp/article/details/7175517
内核源码: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);
- else
- printf("else: a = %d\n", a);
- return 0;
- }
分别输入整数0到4来进行5次测试,它们的输出分别为:
- else: a = 0
- if: a = 1
- if: a = 2
- if: a = 3
- if: 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 5
- int 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函数【转】的更多相关文章
- SQL 中详解round(),floor(),ceiling()函数的用法和区别?
SQL 中详解round(),floor(),ceiling()函数的用法和区别? 原创 2013年06月09日 14:00:21 摘自:http://blog.csdn.net/yueliang ...
- 第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样?
第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样? 一. 案例说明 我们上节提到了,使用property函数定义的属性不要与类内已经定义的普通实例变量重 ...
- 第7.24节 Python案例详解:使用property函数定义属性简化属性访问代码实现
第7.24节 Python案例详解:使用property函数定义属性简化属性访问代码实现 一. 案例说明 本节将通过一个案例介绍怎么使用property定义快捷的属性访问.案例中使用Rectan ...
- 详解wait和waitpid函数
#include <sys/types.h> /* 提供类型pid_t的定义 */ #include <sys/wait.h> pid_t wait(int *status) ...
- Linux 信号详解一(signal函数)
信号列表 SIGABRT 进程停止运行 SIGALRM 警告钟 SIGFPE 算述运算例外 SIGHUP 系统挂断 SIGILL 非法指令 SIGINT 终端中断 SIGKILL 停止进程(此信号不能 ...
- (译)详解javascript立即执行函数表达式(IIFE)
写在前面 这是一篇译文,原文:Immediately-Invoked Function Expression (IIFE) 原文是一篇很经典的讲解IIFE的文章,很适合收藏.本文虽然是译文,但是直译的 ...
- 《Windows驱动开发技术详解》之派遣函数
驱动程序的主要功能是负责处理I/O请求,其中大部分I/O请求是在派遣函数中处理的.用户模式下所有对驱动程序的I/O请求,全部由操作系统转化为一个叫做IRP的数据结构,不同的IRP数据会被“派遣”到不同 ...
- [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口
函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...
- 详解MySQL中concat函数的用法(连接字符串)
MySQL中concat函数 使用方法: CONCAT(str1,str2,…) 返回结果为连接参数产生的字符串.如有任何一个参数为NULL ,则返回值为 NULL. 注意: 如果所有参数均为非二进制 ...
- 详解javascript立即执行函数表达式(IIFE)
立即执行函数,就是在定义函数的时候直接执行,这里不是申明函数而是一个函数表达式 1.问题 在javascript中,每一个函数在被调用的时候都会创建一个执行上下文,在函数内部定义的变量和函数只能在该函 ...
随机推荐
- 洛谷 [P2148] E&G
SG函数的应用 首先每一组都是独立的,所以我们可以求出每一组的SG值异或出来. 那么怎么求每一组的SG值呢,网上的题解都是打表找规律,但其实这个规律是可以证明的 先看规律: x为奇数,y为奇数:SG= ...
- VirtualBox 5.0.10 中 Fedora 23 在安装了增强工具后无法自动调节虚拟机分辨率的问题(改)
VirtualBox 5.0.10 中安装 Fedora 23,即使在安装了增强工具后,仍然会发现虚拟机无法根据 VirtualBox 的运行窗口大小自动进行分辨率调节.究其原因,主要是因为 Fedo ...
- 解决三星 BIOS 模式没有 Fast Bios Mode选项 U盘动项问题
今天想分下盘,进入biso竟然没有网上说 Fast Bios Mode选项,最后自己误打误撞竟然设置成功了,太不可思议了官方这么说:开机按F2进入BIOS设置,找到Boot选项下Boot Device ...
- jquery的固定定位效果
今天做了个固定定位的效果.比如对导航需要进行固定定位效果: 当没有滚动到导航下面,导航正常显示. 当滚动到导航下面,导航就固定到顶部. 这个效果使用了jquery的方法实现,具体思路为: 1)首先获取 ...
- Hive入门及常用指令
基础命令show databases; # 查看某个数据库use 数据库; # 进入某个数据库show tables; # 展示所有表desc 表名; # 显示表结构show partitions 表 ...
- hadoop学习 的yarn
Yarn的产生 mapReduc1.0 1单点故障 2扩展效率低 3资源利用率高 降低运维成本 方便数据共享 多计算框架支持 MapReduce Spark Storm Yarn的架构图 Yarn模块 ...
- shell mysql 直接创建表
shell 直接创建表 #!/bin/bash mysql -hdatabases -uroot -p^xxxxasdasdadd <<EOF Create Database If Not ...
- UI标签库专题二:JEECG智能开发平台Column(列) 子标签
UI标签库专题二:JEECG智能开发平台Column(列) 子标签 1.1. Column(列) 子标签 1.1.1. 演示样例 <t:dgCol title="年龄" ...
- SpringBoot学习之启动报错【This application has no explicit mapping for /error.....】
今天做SpringBoot小例子,在请求controller层的时候出现如下问题. Whitelabel Error Page This application has no explicit map ...
- C语言连接MySQL(codeblocks)
#include <stdio.h> #include <winsock2.h> #include <mysql.h> /*数据库连接用宏*/ #define HO ...