提高编译效率:Unity Builds

最近,我发现了一个方法来减少在C/C++项目的编译时间,就是所谓的Unity Builds(UB)。这项技术非常简单, 通过减少磁盘访问的数量而减少了编译时间。

在编译过程中include的文件会被多次访问, 每一个编译单元(Translation Unit,指的是编译出一个object文件的过程)都会访问到。除非你用一个固态磁盘,不然一般的硬盘一定会拖慢编译过程。

在示例的项目中,有两个假的编译单元,t1.cpp和t2.cpp,都包含相同的头文件ub/b.h, 而它自己又引用了ub/a.h。为了方便验证,在MSVC中打开showIncludes (译注:在项目属性里C/C++->Advanced->Show Includes), 你将看到一个类似这样的输出(*译注,如果没有看到,试试清一下工程再编译。):

Compiling...
t2.cpp
Note: including file: b.h
Note: including file:  a.h
t1.cpp
Note: including file: b.h
Note: including file:  a.h

可以看到,每个编译单元都打开了相同的头文件。UB的目的就是减少这些费时费力的事(比如. 引用的文件), 具体的做法就是将多个translation unit由一个单一的translation unit来代替。


新增一个文件ub.cpp, 内容如下:

#include 
#include 


从项目里去掉t1.cpp和t2.cpp, 然后编译。 这次的输出类似如下这样:

Compiling...
ub.cpp
Note: including file: t1.cpp
Note: including file:  b.h
Note: including file:   a.h
Note: including file: t2.cpp

同样也是4个引用的文件。有没有性能提升呢? 结果是肯定的,第一次遇到b.h会同时引发对a.h的解析,可是第二次遇到b.h时就不需要再解析了。
对于一些有着很深的引用层次和大量编译单元的项目来说,Unity Builds的做法绝对会节省大量的编译时间。


/*译注,作者下面介绍了为CMake编写的自动脚本,此处略去。具体的应用还是要看各个编译器的做法。*/


性能提升
下面这个图显示出了Unity Builds对于编译时间的贡献。所用的项目都是由公司开发的一些库和单元测试项目。
      

实践要点

持续集成
相对于The Magic of Unity Builds中观点, 因为一点修改会导致整个unity unit的重新编译,所以最好不要用于平时的开发工作。倒是可以考虑在CI服务器上执行,这样可以节省大量的时间来跑自动化测试。

单元切分
在一个unity unit包含太多的文件,可能会引起内存不足的问题。即便你的内存够大,最好也不要都放在一起。


代码质量

引入Unity Builds会隐藏一些编码问题,比如重复的代码。因为是将一些translation unit放到一起,就很容易导致重复定义的问题。

原文地址: Reducing Compilation Time: Unity Builds

转载请注明出处: http://blog.csdn.net/horkychen
链接:
  * Unity Builds CMake Demo Project
  * The Evils of Unity Builds
   * 浅谈怎样加快C++代码的编译速度


你可能感兴趣的:(生产力,WebKit,编译,WebKit)