您的位置:首页 > 编程语言 > C语言/C++

对《如何加快C++代码的编译速度的几种技巧》文中提到的方法进行思考

2010-12-20 17:56 585 查看
原文见

http://www.cnblogs.com/vacuum/archive/2010/03/08/1681085.html

首先应该肯定的是,这是一篇很好的文章,尤其对C++编译速度关系的更应该值得一读。
针对文中提到的各种各样的方法,结合ttcn3新执行器项目面对的问题进行一次深刻思考,是有必要的。

文章开头首先对C++编译模式进行了介绍,并分析出为什么会比较慢的原因,相信很多人都是有共鸣的。
编译慢的问题在大工程中尤其明显,我说的是你面对几十万行以上的代码,且需要重复编译的时候。
在我的项目里面,这的确是一个很头痛的问题。
当然,从后来的持续改进中,我承认,之前的确是走了很多弯路,如果少走点弯路,相信会有个更好的endding。

一、代码角度

1、在头文件中使用前置声明,而不是直接包含头文件。
OK,首先大家要清楚什么时候可以使用前置声明代替包含头文件,这个是很重要的point。
返回值?参数?成员变量?
返回值和参数好办,大不了将实现部分搬到cpp中去,但成员变量呢?
在我们的项目中有这样的复杂结构,包含大量复杂结构的子域。。。
因为是基于转换器实现,为了直观方便的使用.和->操作符,倾向于结构体成员作为成员变量。
后来,发现C++构造函数问题,you know,复杂结构的构造是一个很耗时耗内存的过程,于是又重构成使用template。。。
我们一直使用复杂方法来解决问题,缺没有决心使用简单方法,入c的指针。
成员指针比成员变量有太多的好处,包括解决头文件引入问题,包括构造函数耗时问题。。。
从前,转换器部分是比较弱的,所以一直为了使用.和->操作符,而置指针而不顾,这的确是一个很大的错误。
现在,成员指针+get方法封装,相信能解决掉这个问题,而且能解决的很好很好。

2、使用Pimpl模式
如果是自己写代码,的确可以多使用PIMPL,但我们的项目是基于转换代码实现的,过多技巧会导致转换复杂度增加。

3、高度模块化
这个从我的项目来说,可以理解成抽象封装能力。
ttcn3执行器项目,对转换器来说,生成越少越简单越直观的代码是最好的,把实现部分代码隐藏在库实现中。
库的代码是预先编译的,只提高h文件方式,对编译速度影响很少。
在我们的持续不断的优化过程中,基本体现出很多这样的动作,极限目标是,ttcn3和cpp的转换比率接近1:1水平,那就是完美了。

4、删除冗余的头文件
这个很有必要,特别对于大项目,代码多了,就容易马虎了事。
团队和个人应该培养适时重构优化代码的习惯。

5、特别注意inline和template
inline涉及到头文件引入时,需要衡量一下是否有必要了。
template对开发非库应用来说,大部分时候都是没有必要的。
特别是对于有继承关系的类来说,template一般可以使用基类+虚函数进行替换。
我们项目使用的大部分template代码,后续基本都废弃掉了,多思考,一般会有更优的方法解决的。

二、综合技巧

1、预编译头文件(PCH)
如果明白了C++的编译模式,就能理解为什么预编译头文件能提升速度了。
我们的项目也使用了这个方法,但头文件部分只能包含库的头文件,转换生成的头文件由于变动频繁,未纳入。

2、Unity Build
这个对大型项目不太实际。

3、ccache
这个应该是编译器做的事情,不太实际。

4、不要有太多的Additional Include Directories
这个我们的项目不涉及太多,带来的提升效果估计也很微。

三、编译资源

1、并行编译
我们的项目是基于普通单机开发者的,不纳入。

2、更好的磁盘
我们的项目是基于普通单机开发者的,不纳入。

3、分布式编译
我们的项目是基于普通单机开发者的,并行编译配置已经是一个麻烦的问题,不纳入。

4、并行,其实还可以这么做。
关于多进场并行编译的工作,是印度人构思并实现的。
具体来说就是将一个编译任务分成多个cl.exe来做,c++是满足独立编译成obj然后统一链接的。
这个方案在双核CPU表现还行(提升15%左右),但CPU占有率太高,并会出现进程切换开销严重,用户体验很不好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: