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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有什么方法可以改善构建/编译时间?相关的知识,希望对你有一定的参考价值。

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

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

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

答案

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

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

另一答案

对于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秒。

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

另一答案

对于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")]
另一答案

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

另一答案

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

另一答案

Buy a faster computer

另一答案

在我之前的工作中,我们在编译时遇到了很大问题,我们使用的策略之一称为信封模式,请参阅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中调试。这是以前工作的原因。

另一答案

如果您使用了大量文件和大量模板化代码(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文件),并且不太可能寻呼到虚拟内存。

编辑在这里关于Unity Builds的堆栈溢出添加couplelinks

另一答案

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

另一答案

请阅读本书。物理结构的主题非常好,您的项目进入不同的文件,重建次数最少。

不幸的是,它是在模板变得非常重要之前编写的。在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

另一答案

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

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

另一答案

打开调试时不要编译。

以上是关于有什么方法可以改善构建/编译时间?的主要内容,如果未能解决你的问题,请参考以下文章

编译时,运行时解释

改善既有代码的设计结合真实的代码案例场景,谈谈我的一些实施方法!

如何为自定义 CPU 创建 C 编译器?

如何有条件地将 C 代码片段编译到我的 Perl 模块?

是否可以动态编译和执行 C# 代码片段?

编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议16~20)