当前位置:  编程技术>综合
本页文章导读:
    ▪linux内核中的likely和unlikely      linux内核中的likely和unlikelyKernel version:2.6.14CPU architecture:ARM920TAuthor:ce123(http://blog.csdn.net/ce123)GCC version:arm-linux-gcc-3.4.1 看内核时经常遇到if(likely( )){}或是if(unlikely( ))这样的语句,不甚了.........
    ▪为SQLite数据库中某个字段的每一行结尾插入一个字符串        update ThirdClass set NAME=REPLACE(NAME,NAME,NAME||'.rtf') ThirdClass 表名 NAME 字段名 .rtf 要添加的字符串 ||或运算符 作者:yangxuanlun 发表于2013-1-11 16:23:50 原文链接 .........
    ▪(iPhone/iPad开发)解决CAStreamBasicDescription在项目中无法编译通过问题      最近在做一个app端录音的功能,仿照苹果官方的“SpeakHere”工程,其中在导入“iPublicUtility”文件夹里面包含几个c++类文件时,一直报例如: ../CAStreamBasicDescription.h:91:0 ../CAStreamBasicDescrip.........

[1]linux内核中的likely和unlikely
    来源: 互联网  发布时间: 2013-11-10

linux内核中的likely和unlikely

Kernel version:2.6.14

CPU architecture:ARM920T

Author:ce123(http://blog.csdn.net/ce123)

GCC version:arm-linux-gcc-3.4.1

看内核时经常遇到if(likely( )){}或是if(unlikely( ))这样的语句,不甚了解,例如(选自kernel/fork.c中copy_process):

	SET_LINKS(p);
	if (unlikely(p->ptrace & PT_PTRACED))
		__ptrace_link(p, current->parent);

下面详细分析一下。

likely() 与 unlikely()是内核中定义的两个宏。位于/include/linux/compiler.h中,具体定义如下:

#define likely(x)	__builtin_expect(!!(x), 1)
#define unlikely(x)	__builtin_expect(!!(x), 0)

__builtin_expect是GCC(version>=2.9)引进的内建函数,其作用就是帮助编译器判断条件跳转的预期值,避免跳转造成时间乱费,有利于代码优化。查阅GCC手册,发现其定义如下(http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html):

 -- 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 value of C must be a compile-time constant.  The
     semantics of the built-in are that it is expected that EXP == C.
     For example:


          if (__builtin_expect (x, 0))
            foo ();


     would indicate 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))
            error ();


     when testing pointer or floating-point values.

大致意思是:可以使用。由于大部分程序员在分支预测方面做得很糟糕,所以GCC提供了__builtin_expect这个内建函数,给编译器提供分支预测信息,以帮助程序员处理分支预测,优化程序。其第一个参数EXP为一个整型表达式,这个内建函数的返回值也是这个EXP,而C为一个编译期常量,这个函数的语义是:你期望EXP表达式的值等于常量C,从而GCC为你优化程序,将符合这个条件的分支放在合适的地方。由于该内建函数只提供了整型表达式,所以如果你要优化其他类型的表达式,可以采用指针的形式。

当GCC的版本较低时(_GNUC_MINOR__ < 96),__builtin_expect直接返回EXP。下面的代码摘自/include/linux/compiler-gcc2.h。

/* These definitions are for GCC v2.x.  */


/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
   a mechanism by which the user can annotate likely branch directions and
   expect the blocks to be reordered appropriately.  Define __builtin_expect
   to nothing for earlier compilers.  */
#include <linux/compiler-gcc.h>


#if __GNUC_MINOR__ < 96
# define __builtin_expect(x, expected_value) (x)
#endif

总结一下:if() 语句照常用, 和以前一样, 只是 如果你觉得if()是1 的可能性非常大的时候, 就在表达式的外面加一个likely(),如果可能性非常小(比如几率非常小),就用unlikely()包裹上。下面我们看一个例子。

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

root@czu:~/桌面/socket# arm-linux-gcc -fprofile-arcs -O2 -c test.c

root@czu:~/桌面/socket# arm-linux-gcc -fprofile-arcs -O2 -o test test.c

root@czu:~/桌面/socket# arm-linux-objdump -D test > test.dis

000088cc <test_likely>:
    88cc:	e3500000 	cmp	r0, #0	; 0x0
    88d0:	e92d4010 	stmdb	sp!, {r4, lr}
    88d4:	e59fc044 	ldr	ip, [pc, #68]	; 8920 <.text+0x148>
    88d8:	e59fe044 	ldr	lr, [pc, #68]	; 8924 <.text+0x14c>
    88dc:	e3a00005 	mov	r0, #5	; 0x5
    88e0:	0a000006 	beq	8900 <test_likely+0x34>//前面通过cmp将r0和0进行比较,因为x=1的概率很大,优先执行不等于0的分支
    88e4:	e89c0018 	ldmia	ip, {r3, r4}
    88e8:	e3a02000 	mov	r2, #0	; 0x0
    88ec:	e3a01001 	mov	r1, #1	; 0x1
    88f0:	e0933001 	adds	r3, r3, r1
    88f4:	e0a44002 	adc	r4, r4, r2
    88f8:	e88c0018 	stmia	ip, {r3, r4}
    88fc:	e8bd8010 	ldmia	sp!, {r4, pc}
    8900:	e89e0006 	ldmia	lr, {r1, r2}
    8904:	e3a04000 	mov	r4, #0	; 0x0
    8908:	e3a03001 	mov	r3, #1	; 0x1
    890c:	e0911003 	adds	r1, r1, r3
    8910:	e0a22004 	adc	r2, r2, r4
    8914:	e3a00006 	mov	r0, #6	; 0x6
    8918:	e88e0006 	stmia	lr, {r1, r2}
    891c:	e8bd8010 	ldmia	sp!, {r4, pc}
    8920:	000121e0 	andeq	r2, r1, r0, ror #3
    8924:	000121e8 	andeq	r2, r1, r8, ror #3

00008928 <test_unlikely>:
    8928:	e3500000 	cmp	r0, #0	; 0x0
    892c:	e92d4010 	stmdb	sp!, {r4, lr}
    8930:	e59fc044 	ldr	ip, [pc, #68]	; 897c <.text+0x1a4>
    8934:	e59fe044 	ldr	lr, [pc, #68]	; 8980 <.text+0x1a8>
    8938:	e3a00005 	mov	r0, #5	; 0x5
    893c:	1a000007 	bne	8960 <test_unlikely+0x38>//前面通过cmp将r0和0进行比较,因为x=0的概率很大,优先执行等于0的分支

    8940:	e89c0018 	ldmia	ip, {r3, r4}
    8944:	e3a02000 	mov	r2, #0	; 0x0
    8948:	e3a01001 	mov	r1, #1	; 0x1
    894c:	e0933001 	adds	r3, r3, r1
    8950:	e0a44002 	adc	r4, r4, r2
    8954:	e3a00006 	mov	r0, #6	; 0x6
    8958:	e88c0018 	stmia	ip, {r3, r4}
    895c:	e8bd8010 	ldmia	sp!, {r4, pc}
    8960:	e89e0006 	ldmia	lr, {r1, r2}
    8964:	e3a04000 	mov	r4, #0	; 0x0
    8968:	e3a03001 	mov	r3, #1	; 0x1
    896c:	e0911003 	adds	r1, r1, r3
    8970:	e0a22004 	adc	r2, r2, r4
    8974:	e88e0006 	stmia	lr, {r1, r2}
    8978:	e8bd8010 	ldmia	sp!, {r4, pc}
    897c:	000121f8 	streqd	r2, [r1], -r8
    8980:	000121f0 	streqd	r2, [r1], -r0

如果我们将代码修改一下,不用这两个宏结果会怎样呢?
//test_builtin_expect.c 
int test_likely(int x)
{
	if(x)
		x = 5;
	else
		x = 6;  
	return x;
}
int test_unlikely(int x)
{
	if(x)
		x = 5;
	else
		x = 6;
	return x;
}
反汇编代码如下:

00008460 <test_likely>:
    8460:	e3500000 	cmp	r0, #0	; 0x0
    8464:	03a00006 	moveq	r0, #6	; 0x6
    8468:	13a00005 	movne	r0, #5	; 0x5
    846c:	e1a0f00e 	mov	pc, lr

00008470 <test_unlikely>:
    8470:	e3500000 	cmp	r0, #0	; 0x0
    8474:	03a00006 	moveq	r0, #6	; 0x6
    8478:	13a00005 	movne	r0, #5	; 0x5
    847c:	e1a0f00e 	mov	pc, lr

如上述例子分析所示,

    
[2]为SQLite数据库中某个字段的每一行结尾插入一个字符串
    来源: 互联网  发布时间: 2013-11-10

 

update ThirdClass set NAME=REPLACE(NAME,NAME,NAME||'.rtf')
ThirdClass 表名
NAME 字段名
.rtf 要添加的字符串
||或运算符
作者:yangxuanlun 发表于2013-1-11 16:23:50 原文链接
阅读:31 评论:0 查看评论

    
[3](iPhone/iPad开发)解决CAStreamBasicDescription在项目中无法编译通过问题
    来源: 互联网  发布时间: 2013-11-10

最近在做一个app端录音的功能,仿照苹果官方的“SpeakHere”工程,其中在导入“iPublicUtility”文件夹里面包含几个c++类文件时,一直报例如:

../CAStreamBasicDescription.h:91:0 ../CAStreamBasicDescription.h:91: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'CAStreamBasicDescription'

字样的错误信息,一直编译不通过,framework文件也一并都导入进去,判定肯定是XCode文件相关配置问题,后来发现是object-c调用c文件时,需要注意,所有调用c头文件的类对应的.m文件应该改成.mm文件,同时项目的.pch文件不要import c类头文件,在用XCode自动生成iOS工程目录文件中,根目录下的.pch文件是项目的所有文件的头文件。

根据这两点,逐一排查.m是否改成.mm文件就行。

作者:andypan1314 发表于2013-1-11 16:15:28 原文链接
阅读:40 评论:0 查看评论

    
最新技术文章:
▪error while loading shared libraries的解決方法    ▪版本控制的极佳实践    ▪安装多个jdk,多个tomcat版本的冲突问题
▪简单选择排序算法    ▪国外 Android资源大集合 和个人学习android收藏    ▪.NET MVC 给loading数据加 ajax 等待loading效果
▪http代理工作原理(3)    ▪关注细节-TWaver Android    ▪Spring怎样把Bean实例暴露出来?
▪java写入excel2007的操作    ▪http代理工作原理(1)    ▪浅谈三层架构
▪http代理工作原理(2)    ▪解析三层架构……如何分层?    ▪linux PS命令
▪secureMRT Linux命令汉字出现乱码    ▪把C++类成员方法直接作为线程回调函数    ▪weak-and算法原理演示(wand)
▪53个要点提高PHP编程效率    ▪linux僵尸进程    ▪java 序列化到mysql数据库中
▪利用ndk编译ffmpeg    ▪活用CSS巧妙解决超长文本内容显示问题    ▪通过DBMS_RANDOM得到随机
▪CodeSmith 使用教程(8): CodeTemplate对象    ▪android4.0 进程回收机制    ▪仿天猫首页-产品分类
▪从Samples中入门IOS开发(四)------ 基于socket的...    ▪工作趣事 之 重装服务器后的网站不能正常访...    ▪java序列化学习笔记
▪Office 2010下VBA Addressof的应用    ▪一起来学ASP.NET Ajax(二)之初识ASP.NET Ajax    ▪更改CentOS yum 源为163的源
▪sharepoint 2010 自定义列表启用版本记录控制 如...    ▪解决UIScrollView截获touch事件的一个极其简单有...    ▪Chain of Responsibility -- 责任链模式 iis7站长之家
▪java设计模式-观察者模式初探    ▪MANIFEST.MF格式总结    ▪Android 4.2 Wifi Display核心分析 (一)
▪Perl 正则表达式 记忆方法    ▪.NET MVC 给loading数据加 ajax 等待laoding效果    ▪java 类之访问权限
▪extjs在myeclipse提示    ▪xml不提示问题    ▪Android应用程序运行的性能设计
▪sharepoint 2010 自定义列表启用版本记录控制 如...    ▪解决UIScrollView截获touch事件的一个极其简单有...    ▪Chain of Responsibility -- 责任链模式
▪运行skyeye缺少libbfd-2.18.50.0.2.20071001.so问题    ▪sharepoint 2010 使用sharepoint脚本STSNavigate方法实...    ▪让javascript显原型!
▪kohana基本安装配置    ▪MVVM开发模式实例解析    ▪sharepoint 2010 设置pdf文件在浏览器中访问
▪spring+hibernate+事务    ▪MyEclipse中文乱码,编码格式设置,文件编码格...    ▪struts+spring+hibernate用jquery实现数据分页异步加...
▪windows平台c++开发"麻烦"总结    ▪Android Wifi几点    ▪Myeclipse中JDBC连接池的配置
▪优化后的冒泡排序算法    ▪elasticsearch RESTful搜索引擎-(java jest 使用[入门])...    ▪MyEclipse下安装SVN插件SubEclipse的方法
▪100个windows平台C++开发错误之七编程    ▪串口转以太网模块WIZ140SR/WIZ145SR 数据手册(版...    ▪初识XML(三)Schema
▪Deep Copy VS Shallow Copy    ▪iphone游戏开发之cocos2d (七) 自定义精灵类,实...    ▪100个windows平台C++开发错误之八编程
▪C++程序的内存布局    ▪将不确定变为确定系列~Linq的批量操作靠的住...    ▪DIV始终保持在浏览器中央,兼容各浏览器版本
▪Activity生命周期管理之三——Stopping或者Restarti...    ▪《C语言参悟之旅》-读书笔记(八)    ▪C++函数参数小结
▪android Content Provider详解九    ▪简单的图片无缝滚动效果    ▪required artifact is missing.
▪c++编程风格----读书笔记(1)    ▪codeforces round 160    ▪【Visual C++】游戏开发笔记四十 浅墨DirectX教程...
▪【D3D11游戏编程】学习笔记十八:模板缓冲区...    ▪codeforces 70D 动态凸包    ▪c++编程风格----读书笔记(2)
▪Android窗口管理服务WindowManagerService计算Activity...    ▪keytool 错误: java.io.FileNotFoundException: MyAndroidKey....    ▪《HTTP权威指南》读书笔记---缓存
▪markdown    ▪[设计模式]总结    ▪网站用户行为分析在用户市场领域的应用
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3