C代码优化经验总结.docx
《C代码优化经验总结.docx》由会员分享,可在线阅读,更多相关《C代码优化经验总结.docx(26页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C+代码优化经验总结优化是一个非常大的主题,本文并不是去深入探讨性能分析理论,算法 的效率,况且我也没有这个能力。我只是想把一些能够简单的应用到你 的C+代码中的优化技术总结在这里,这样,当你遇到几种不一致的编 程策略的时候,就能够对每种策略的性能进行一个大概的估计。这也是 本文的目的之所在.目录:一.优化之前二.声明的放置三.内联函数.优化你的内存使用四 .速度优化.最后的求助一.优化之前在进行优化之前,我们首先应该做的是发现我们代码的瓶颈(bottleneck)在哪里。1 .我们先来看看内联函数给我们带来的好处:从一个用户的角度来看,内联函数看起来与普通函数一样,它能够有参数与返回值,也能
2、够有自己的作用域, 然而它却不可能引入通常函数调用所带来的负担。另外,它能够比宏更安全更容易调试。当然有一点应该意识到,inline specifier仅仅是对编译器的 建议,编译器有权利忽略这个建议。那么编译器是如何决定函数内联与否呢?通常情况下 关键性因素包含函数体的大小,是否有局部对象被声明,函数的复杂性等等。2 .那么假如一个函数被声明为inline但是却没有被内联将会发生 什么呢?理论上,当编译器拒绝内联一个函数的时候,那个函数会像普通函数一样被对待,但是还会出现一些其他的问题。比如下面这段代码:/ Time, h#include#includeusing namespace std
3、;class Time(public:inline void Show() for (int i = 0; i10; i+) couttime(0)endl;);由于成员函数Time: Show()包含一个局部变量与一个for循环,因 此编译器通常拒绝inline,同时把它当作一个普通的成员函数。但是这个包含类声明的头文 件会被单独的#include进各个独立的编译单元中:/ fl. cpp1 i 11 T *1 ffmclude 1 ime. njvoid fl ()Time tl;tl. Show();)/ f2. cppttinclude Time. hvoid f2 ()(Time t
4、2;t2. Show();)结果编译器为这个程序生成了两个相同成员函数的拷贝:void fl ();void f2 ();int main ()fl();f2();return 0;)当程序被链接的时候,linker将会面对两个相同的Time: :Show。拷贝,因此函数重定义的连接错误发生。但是老一些的C+实现应付这种情况的办法是通过把一个un-inlined函数当作static来处理。因此每一份函数拷贝仅仅在自己的编译单元 中可见,这样链接错误就解决了,但是在程序中却会留下多份函数拷贝。在这种情况下,程序的性能不但没有提升,反而增加了编译与链接时间与最终可执行体的大小。但是幸运的是,新的C
5、+标准中关于un-inlined函数的说法已 经改变。一个符合标准C+实现应该只生成一份函数拷贝。然而,要想所有的编译器都支持这 一点可能还需要很长时间。另外关于内联函数还有两个更令人头疼的问题。第一个问题是 该如何进行保护。一个函数开始的时候可能以内联的形式出现,但是随着系统的扩展,函 数体可能要求添加额外的功能,结果内联函数就变得不太可能,因此需要把inline specifier去除与把函数体放到一个单独的源文件中。另一个问题是当内联函数被应用在代码 库的时候产生。当内联函数改变的时候,用户务必重新编译他们的代码以反映这种改变。然而关于一个非内联函数,用户仅仅需要重新链接就能够了。这里想
6、要说的是,内联函数并不是一个增强性能的灵丹妙药。只有当函数非常短小的时候它才能得到我们想要的效果,但是假如函数并不是很短而且在 很多地方都被调用的话,那么将会使得可执行体的体积增大。最令人烦恼的还是当编译器 拒绝内联的时候。在老的实现中,结果很不尽人意,尽管在新的实现中有很大的改善,但 是仍然还是不那么完善的。一些编译器能够足够的聪明来指出什么函数能够内联什么不能, 但是,大多数编译器就不那么聪明了,因此这就需要我们的经验来推断。假如内联函数 不能增强行能,就避免使用它!四.优化你的内存使用通常优化都有几个方面:更快的运行速度,有效的系统资源使用,更小的内存使用。通常情况下,代码优化都是试图在
7、以上各个方面进行改善。重新放 置声明技术被证明是消除多余对象的建立与销毁,这样既减小了程序的大小又加快了运行 速度。然而其他的优化技术都是基于一个方面更快的速度或者者是更小的内存使用。有的时候,这些目标是互斥的,压缩了内存的使用往往却减慢了代码速度,快速的代码却又需 要更多的内存支持。下面总结两种在内存使用上的优化方法:1. Bit Fields在C/C+中都能够存取与访问数据的最小构成单元:bito由于 bit并不是C/C+基本的存取单元,因此这里是通过牺牲运行速度来减少内存与辅助存储器 的空间的使用。注意:一些硬件结构可能提供了特殊的处理器指令来存取bit,因此bitfields是否影响程
8、序的速度取决于具体平台。在我们的现实生活中,一个数据的许多位都被浪费了,由于某些应用根本就不可能有那么大的数据范围。也许你会说,bit是如此之小,通过它就能减小 存储空间的使用吗?的确,在数据量很小的情况下不可能看出什么效果,但是在数据量惊人 的情况下,它所节约的空间还是能够让我们的眼睛为之一亮的。也许你又会说,现在内存与 硬盘越来越便宜,何苦要费半天劲,这省不了几个钱。但是还有另外一个原因一定会使你 信服,那就是数字信息传输。一个分布式数据库都会在不一致的地点有多份拷贝。那么数 百万的纪录传输就会显得十分昂贵。Ok,现在我们就来看看该如何做吧,首先看下面这段代 码:struct Billin
9、gReclong cust_id;long timestamp;enum CallType toll_free, local, regional, long_distance, international, cellular type;enum CallTariff off_peak, medium_rate, peak_time tariff;);上面这个结构体在32位的机器上将会占用16字节,你会发现其中 有许多位都被浪费了,尤其是那两个enum型,浪费更是严重,因此请看下面做出的改进:struct BillingRec(int custid: 24; / 23 bits + 1 sign
10、 bitint timestamp: 24;enum CallType/. . .);enum CallTariff/.然而当你做这件情况的时候切忌从一个debug-version进行推断,由于 debug-version 中包含了许多额外的代码。一个debug-version可执行体要比release-version 大出 40%。那些额外的代码都是用来支持调试的,比如说符号的查找。大多数实现都为 debug-version 与 release-version提供了不一致的operator new与库函数。而且,一个release-version 的执彳亍体可能已经通过多种途径进行了优化,包
11、含不必要的临时对象的消 除,循环展开,把对象移入寄存器,内联等等。另外,我们要把调试与优化区分开来,它们是在完成不一致的 任务。 debug-version 是用来追捕bugs与检查程序是否有逻辑上的问题。release-version 则是用来做一些性能上的调整与进行优化。下面就让我们来看看有什么代码优化技术吧!unsigned call: 3;unsigned tariff: 2;);现在一个数据从16字节缩减到了 8字节,减少了一半,怎么样,效 果还是显著的吧:)2. UnionsUnions通过把两个或者更多的数据成员放置在相同地址的内存中来减少内存浪费,这就要求在任何时间只能有一个数
12、据成员有效。Union能够有成员函数, 包含构造函数与析构函数,但是它不能有虚函数。C+支持anonymous unionso anonymous union是一个未命名类型的未命名对象。比如:union long n; void * p; / anonymousn 二 lOOOL; / members are directly accessed p = 0; / n is now also 0不像命名的union,它不能有成员函数与非public的数据成员。那么unions什么时候是有用的呢?下面这个类从数据库中获取一 个人的信息。关键字既可以是一个特有的ID或者者人名,但是二者却不能同时有
13、效:class PersonalDetailsprivate:char * name;long ID;/.public:PersonalDetails (const char *nm); /key is of type char * usedPersonalDetails(long id) : ID(id) /numeric key used上面这段代码中就会造成内存的浪费,由于在一个时间只能有一个 关键字有效。anonymousunion能够在这里使用来减少内存的使用,比如:class PersonalDetailsprivate:union /anonymouschar * name;lo
14、ng ID;public:PersonalDetails (const char *nm);PersonalDetails(long id) : ID (id) /*/ / directaccess to a member;通过使用union, PersonalDetails类的大小被减半。但是这里要说 明的是,节约4个字节内存并不值得引入union所带来的烦恼,除非这个类作为数百万数 据库记录的类型或者者纪录在一条很慢的通信线路传输。值得注意的是unions并不引入任何运 行期负担,因此这里不会有什么速度上的缺失。anonymous union的优点就是它的成员能 够被直接访问。五.速度优化
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 代码优化经验总结 代码 优化 经验总结
限制150内