这个问题可能有些奇怪,但我怎样才能加快g ++编译时间?我的C ++代码大量使用boost和模板。我已经尽可能多地从头文件中移动并使用-j选项,但是编译(和链接)仍需要很长时间。
是否有任何工具可以分析我的代码并指出编译器的瓶颈?或者可以以某种方式分析在我的代码上运行的编译器?这将是非常好的,因为有时我会有这样的印象,我花了太多时间盯着编译器控制台日志......
答案 0 :(得分:48)
对我来说最有用的是:
-j3
为make。但是,确保您的Makefile中的依赖关系图是正确的,否则您可能会遇到问题。-O0
(并且您的计算机足够快,以至于您不必过多关注(可能很小的)性能损失。)答案 1 :(得分:17)
以下是我在您描述的非常类似的场景(boost,templates,gcc)中加快构建的所有工作
答案 2 :(得分:17)
我认为我们正在讨论分钟来编译文件,即预编译头文件或本地磁盘问题不是问题。
深度模板代码(boost等)的长编译时间通常源于gcc在模板实例化时的不友好的渐近行为,特别是当使用模板默认参数模拟可变参数模板时。
这是一个文档,它将减少的编译时间命名为可变参数模板的动机:
cpptruths有一篇关于gcc-4.5如何代表这一点以及它如何通过其可变参数模板表现出色的文章:
IIRC然后BOOST有办法限制伪变量的模板默认参数的生成,我认为'g ++ -DBOOST_MPL_LIMIT_LIST_SIZE = 10'应该有效(默认为20)
UPDATE:还有一个很好的线程,通常的技术可以加速在SO上进行编译,这可能很有用:
更新:这是关于编译模板时的性能问题,接受的答案也是建议使用gcc-4.5,同时也提到了clang作为正面例子:
答案 3 :(得分:9)
如果您正在进行大量重新编译,ccache可能有所帮助。它实际上并没有加快编译速度,但如果您因某些原因碰巧进行了无用的重新编译,它将为您提供缓存结果。它可能给人一种解决错误问题的印象,但有时重建规则非常复杂,以至于你在新版本中实际上最终会采用相同的编译步骤。
其他想法:如果您的代码使用clang进行编译,请改用它。它通常比gcc快。
答案 4 :(得分:3)
除了其他人添加的内容以及您已经在做的事情(并行化构建,编译器选项等)之外,考虑将模板隐藏在实现类中,通过接口访问。这意味着,而不是像这样的类:
// ClsWithNoTemplates.h file, included everywhere
class ClsWithTemplates
{
ComplicatedTemplate<abc> member;
// ...
public:
void FunctionUsingYourMember();
};
你应该:
// ClsWithNoTemplates.h file:
class ClsWithTemplatesImplementation; // forward declaration
// definition included in the ClsWithNoTemplates.cpp file
// this class will have a ComplicatedTemplate<abc> member, but it is only
// included in your ClsWithNoTemplates definition file (that is only included once)
class ClsWithNoTemplates
{
ClsWithTemplatesImplementation * impl; // no templates mentioned anywhere here
public:
void FunctionUsingYourMember(); // call impl->FunctionUsingYourMember() internally
};
这会改变你的OOP设计,但这是好事:包括'ClsWithNoTemplates'的定义现在是 fast 而你只是(pre)编译'ClsWithNoTemplates'的定义一次。< / p>
另外,如果更改实现代码,则可能不需要重新定义包含ClsWithNoTemplates.h的任何代码。
此更改应显着增加您的部分编译时间,并且在ClsWithNoTemplates是从库文件导出的公共接口的情况下也会有所帮助:因为当您仅更改实现时,您的相关客户端不会更改文件代码根本不需要重新编译。
答案 5 :(得分:3)
尝试PIMPL技术,这个问题:What techniques can be used to speed up C++ compilation times?
它会阻止编译器在每次需要执行某些操作时跟踪头文件和实现链。
答案 6 :(得分:2)
如果有很多文件,只需要一个#include所有其他.cpp文件的.cpp文件,就可以加快编译速度。这当然要求您对宏更加小心,并且已经为每个文件定义了,因为它们现在对其他cpp文件可见。
如果文件很多,这可以减少编译时间。
答案 7 :(得分:1)
实例化较少的模板和内联函数。尽可能预编译,只需链接它,而不是从头开始编译所有内容。确保您使用的是最新版本的GCC。
然而,这是一个简单的事实,C ++是一种非常复杂的语言,编译需要相当长的时间。
答案 8 :(得分:1)
This paper描述了一种编译模板代码的方法,就像“传统的”非模板对象文件一样。保存编译和放大链接时间,每个模板实例化只需要一行代码开销。
答案 9 :(得分:0)
通常,编译中最昂贵的部分是(a)读取源文件( ALL )和(b)将编译器加载到每个源文件的内存中。
如果你有52个源(.cc)文件,每个文件#includes 47个#include(.h)文件,你将加载编译器52次,并且你将要翻阅2496个文件。根据文件中注释的密度,您可能花费大量时间吃无用的字符。 (在我看到的一个组织中,头文件在66%到90%的注释之间变化,只有10%-33%的文件是“有意义的”。为提高这些文件的可读性,可以做的唯一最好的事情就是剥离每个最后的评论,只留下代码。)
详细了解您的计划的实际组织方式。了解您是否可以合并源文件,并简化#include文件的层次结构。
几十年前,像IBM这样的公司理解这一点,并且会编写他们的编译器,以便编译器可以传递一个文件列表来编译,而不仅仅是一个文件,编译器只能加载一次。答案 10 :(得分:0)
使用多核编译g ++