gcc/linux内核中likely、unlikely和__attribute__(section(""))属性
查看linux内核源码,你会发现有很多if (likely(""))...及if (unlikely(""))...语句,这些语句其实是编译器的一种优化方式,具体分析如下:
likely及unlikely是一个宏定义:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
likely()的 意思是认为这个分支最有可能发生,如if (likely(x == 0)){...},这个语句表示x等于0最有可能发生,其实语意就相当于if (x == 0){...},只不过likely针
对程序指令运行做了优化,不去做一些无谓的指令跳转;unlikely()意思相反,就是最不可能发生,注意if (unlikely(x == 0))还是相当于if (x==0)的逻辑。
如果需要更进一步了解likely()就必须要深入了解__bulitin_expect(!!(x), 1)函数。
— 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 semantics of the built-in are that it is expected that exp == c. For example:
if (__builtin_expect (x, 0))
foo ();
indicates 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))
foo (*ptr);
when testing pointer or floating-point values.
文档链接:https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#Other-Builtins
从gcc官方文档来看,内建函数long __builtin_expect (long exp, long c)主要用于优化程序的分支预测,减少程序的指令跳转,现代处理器一般都是流水线架构,
很多芯片级的优化是靠流水线预取完成的,所以我们的程序优化也是需要尽量减少跳转。
文档也提到了由于大部分程序员根本就不了解自己程序的运行情况,所以推荐我们在编译时加上-fprofile-arcs选项去评估我们的程序分支运行情况;-fprofile-arcs选
项是代码覆盖率测试工具gcov使用时需要增加的编译选项,gcov能够去统计及分析我们的程序的分支运行情况,关于gcov的使用这里不做介绍,只需要知道gcov是
一个测试统计工具,配合-fprofile-arcs工具使用,__builtin_expect 根据gcov的分析结果来做实际的分支预测优化。
这里可以大家还会有疑问,为什么#define likely(x) __builtin_expect(!!(x), 1)中要使用!!(x),这其实是因为函数__builtin_expect (long exp, long c)期望是
exp == c,这时的1相当于bool值true,所以exp需要是一个bool表达式,通过!!可以变成bool表达式而不改变原有函数,这样才能够正确的与1或0(bool值)做匹配
判断;试想如果没有!!,即#define likely(x) __builtin_expect((x), 1),那么likely(10)原本是希望表达式是true,但是根据函数的处理逻辑10 != 1,那么优化会
以false的结果来优化,这样就阴差阳错了!!!
最后讲述一下__attribute__(section(""))属性,这个属性比较好理解,就是为某个函数或变量指定section,比如:
int __attribute__(section(".test.data")) value = 0;
这样的话变量value将会被放在.test.data段中;
void __attribute__((section(".test.text"))) func(void){}
这样函数func会被放入.test.text段中。
查看section信息可以通过如下命令:readelf -S xxx,可以查看可执行文件也可以是目标文件.o,关于section这里不过多介绍,只要大概知道一般我们的代码都是
放在.text段,全局变量一般放在.data段,我们通过__attribute__((""))定义的符号就放在我们特定的section里面。
gcc/linux内核中likely、unlikely和__attribute__(section(""))属性的更多相关文章
- Linux 内核中的 GCC 特性
https://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux 完全依靠 ...
- Linux内核中的fastcall和asmlinkage宏
代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...
- [翻译] Linux 内核中的位数组和位操作
目录 Linux 内核里的数据结构 原文链接与说明 Linux 内核中的位数组和位操作 位数组声明 体系结构特定的位操作 通用位操作 链接 Linux 内核里的数据结构 原文链接与说明 https:/ ...
- 嵌入式C语言自我修养 01:Linux 内核中的GNU C语言语法扩展
1.1 Linux 内核驱动中的奇怪语法 大家在看一些 GNU 开源软件,或者阅读 Linux 内核.驱动源码时会发现,在 Linux 内核源码中,有大量的 C 程序看起来“怪怪的”.说它是C语言吧, ...
- Linux内核中双向链表的经典实现
概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...
- linux内核中的get_user和put_user
linux内核中的get_user和put_user 在 内核空间和用户空间交换数据时,get_user和put_user是两个两用的函数.相对于copy_to_user和 copy_from_use ...
- Linux内核中的常用宏container_of
Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...
- Linux内核中的jiffies及其作用介绍及jiffies等相关函数详解
在LINUX的时钟中断中涉及至二个全局变量一个是xtime,它是timeval数据结构变量,另一个则是jiffies,首先看timeval结构struct timeval{time_t tv_sec; ...
- Linux内核中的常用宏container_of其实很简单【转】
转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...
随机推荐
- SQL Server 合并复制遇到identity range check报错的解决
最近帮一个客户搭建跨洋的合并复制,由于数据库非常大,跨洋网络条件不稳定,因此只能通过备份初始化,在初始化完成后向海外订阅端插入数据时发现报出如下错误: Msg 548, Level 16, S ...
- C#-正则,常用几种数据解析-端午快乐
在等待几个小时就是端午节了,这里预祝各位节日快乐. 这里分享的是几个在C#中常用的正则解析数据写法,其实就是Regex类,至于正则的匹配格式,请仔细阅读正则的api文档,此处不具体说明,谢谢. 开始吧 ...
- Hawk 4.2 过滤器
过滤器可以在流中,过滤掉不符合条件的文档.当然也可勾选反向,此时只会留下不符合条件的文档. 空对象过滤器 最为常用,需要列名,可以过滤掉所有内容为Null,或字符串全部都是空字符的情况 数值范围过滤 ...
- .NET Core全面扫盲贴
标签: .NETCore Asp.NETCore 1. 前言 2. .NET Core 简介 2.1 .NET Core是什么 2.2 .NET Core的组成 2.3 .NET Core的特性 2. ...
- 解决NTKO Office中文文件名保存到服务器时出现乱码的问题
再使用NTKO office控件时,在ntko往服务器提交文件时,中文文件名会出现乱码的问题! 其实解决这个问题可以换一种思路,在ntko往服务器提交文件时英文肯定是不会出现乱码的问题的! 那么想办法 ...
- php注释规范
注释在写代码的过程中非常重要,好的注释能让你的代码读起来更轻松,在写代码的时候一定要注意注释的规范.(李昌辉) php里面常见的几种注释方式: 1.文件头的注释,介绍文件名,功能以及作者版本号等信息 ...
- 仿QQ空间根据位置弹出PopupWindow显示更多操作效果
我们打开QQ空间的时候有个箭头按钮点击之后弹出PopupWindow会根据位置的变化显示在箭头的上方还是下方,比普通的PopupWindow弹在屏幕中间显示好看的多. 先看QQ空间效果图: ...
- ngrok
为什么要使用ngrok?/ngrok 作为一个Web开发者,我们有时候会需要临时地将一个本地的Web网站部署到外网,以供它人体验评价或协助调试等等,通常我们会这么做: 找到一台运行于外网的Web服务器 ...
- SharePoint 部署时报错: 未能提取此解决方案中的cab文件
在vs里右击SharePoint项目,选择"部署",结果报错: Error occurred in deployment step 'Add Solution':Fail to e ...
- Sencha, the nightmare!
基础 创建一个应用程序 sencha -sdk /path/to/sdk generate app %name% /path/to/app 跑起来 cd /path/to/app sencha app ...