有什么方法可以改善构建/编译时间?

时间:2009-10-08 17:34:20

标签: performance language-agnostic build-process build

我正在使用Visual Studio,似乎摆脱未使用的引用和使用语句可以加快我在大型项目上的构建时间。是否有其他已知的加速构建时间的方法。其他语言和构建环境怎么样?

构建/编译期间通常的瓶颈是什么?磁盘,CPU,内存?

什么是分布式构建的良好参考列表?

12 个答案:

答案 0 :(得分:6)

我们为大型C ++项目所做的最大改进是分发我们的构建。几年前,完整版本需要大约半个小时,而现在大约需要三分钟,其中三分之一是链接时间。

我们正在使用专有的构建系统,但IncrediBuild适用于很多人(我们无法让它可靠地工作)。

答案 1 :(得分:3)

修复编译器警告应该有所帮助。

答案 2 :(得分:3)

答案 3 :(得分:3)

在我以前的工作中,编译时遇到了很大问题,我们使用的策略之一称为信封模式,请参阅here

基本上,它尝试通过最小化标头大小来最小化预处理器在标头中复制的代码量。它通过将任何非公开的东西移动到私人朋友类来实现这一点,这是一个例子。

foo.h中:

class FooPrivate;
class Foo
{
public:
   Foo();
   virtual ~Foo();
   void bar();
private:
   friend class FooPrivate;
   FooPrivate *foo;
};

Foo.cpp中:

Foo::Foo()
{
   foo = new FooPrivate();
}

class FooPrivate
{
    int privData;
    char *morePrivData;
};

您执行此操作的包含文件越多,添加的越多。它确实有助于你的编译时间。

虽然我学到了很多困难,但确实很难在VC6中调试。这是以前工作的原因。

答案 4 :(得分:2)

请阅读本书。在物理结构的主题上,将项目放入不同的文件并进行最少的重建是非常好的。

不幸的是,它是在模板变得非常重要之前编写的。在C ++编译方面,模板是实时杀手。 Especialls如果你犯了错误并且到处使用智能指针。在这种情况下,您只能继续升级到最新的CPU和最新的SSD驱动器。如果使用预编译头文件,MSVC已经是现有C ++编译器的紧固件。

http://ecx.images-amazon.com/images/I/51HNJ7KBBAL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg

答案 5 :(得分:2)

如果您使用了大量文件和大量模板化代码(STL / BOOST /等),那么Bulk或Unity版本应该减少构建和链接时间。

Bulk Builds将您的项目分解为子部分并将该子部分中的所有CPP文件包含在单个文件中的想法。 Unity构建通过编译一个包含所有其他CPP文件的单个CPP文件来进一步实现这一点。

这通常更快的原因是:

1)每个批量文件

仅评估模板一次

2)每个批量文件只打开/处理包含文件一次(假设包含文件中有一个正确的#ifndef FILE__FILENAME__H / #define FILE__FILENAME__H / #endif包装器)。减少总I / O对于编译时来说是件好事。

3)链接器使用的数据少得多(Single Unity OBJ文件或多个批量OBJ文件),并且不太可能寻呼到虚拟内存。

编辑在此处添加couple links关于Unity Build的堆栈溢出。

答案 6 :(得分:2)

警惕广泛的“在项目中考虑此目录和所有子目录以包含头”包含类型设置。这将导致编译器必须迭代每个目录,直到找到所请求的头文件,并且对于您在项目中包含的许多头文件而言,这可能是非常昂贵的操作。

答案 7 :(得分:1)

Visual Studio支持并行构建,这可能有所帮助,但真正的瓶颈是磁盘IO。

例如在C中 - 如果生成LST文件,则编译将需要很长时间。

答案 8 :(得分:0)

打开调试时不要编译。

答案 9 :(得分:0)

对于C ++,市长瓶颈是磁盘I / O.许多标题包括来回的其他标题,这会导致为每个编译单元打开和读取大量文件。

如果将源移动到RAM磁盘,则可以获得显着改进。如果您确保源文件只读取一次,则更多。

因此,对于新项目,我开始将所有内容都包含在一个名为_.cpp的文件中。它的结构是这样的:

/* Standard headers */
#include <vector>
#include <cstdio>
//...

/* My global macros*/
#define MY_ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0]))

// My headers
#include "foo.h"
#include "bar.h"
//...

// My modules
#include "foo.cpp"
#include "bar.cpp"

我只编译这个单个文件。

我的标头和源文件不包含任何内容,并使用命名空间来避免与其他模块发生冲突。

每当我的程序遗漏某些内容时,我只将其标题和来源添加到此模块中。

这样,每个源文件和标头只读取一次,并且构建非常快。编译时间仅在添加更多文件时呈线性增加,但不能以二次方式增加。 我的爱好项目大约是40000 loc和500个模块,但仍然可以编译大约10-20秒。如果我将所有源和标头移动到RAM磁盘中,则编译时间减少到3秒。

缺点是,现有的代码库很难重构使用这个方案。

答案 10 :(得分:0)

对于C# - 使用程序集的固定版本而不是自动增量版本可以大大加快后续本地构建。

的AssemblyInfo.cs

// takes longer to update version number changes on all references to this assembly
[assembly: AssemblyVersion("1.0.*")]

// this way already built assemblies do not need to be recompiled 
// to update version number changes.
[assembly: AssemblyVersion("1.0.0.0")]

答案 11 :(得分:0)

编译时间和脆弱的基类问题:我写了一篇关于改进C ++编译时间的博客。 Link