0

我们正在开发一个C++ 库,目前包含超过 50000 个单独的 .cpp 文件。这些都被编译并归档到一个静态库中。即使使用并行构建,这也需要几分钟。我想减少这个编译时间。

每个文件平均有 110 行,其中包含一个或两个函数。但是,对于每个 .cpp 文件,都有一个对应的 .h 标头,并且这些标头通常包含在许多 .cpp 文件中。例如,A.h可能包含在A.cppB.cppC.cpp等中。

我首先想介绍一下编译过程。有没有办法找出在做什么上花费了多少时间?我担心打开头文件只是为了检查包含保护并忽略文件而浪费了大量时间。

如果这种事情是罪魁祸首,那么减少编译时间的最佳做法是什么?

我愿意添加新的分组标题,但可能不愿意更改这种多文件布局,因为这允许我们的库也可以根据需要用作仅标题库。

4

4 回答 4

4

真的很难说。

我在工作中致力于改善我们项目的编译时间,发现一个文件花了 15 分钟(在 编译时-O2,但在 15 秒左右-O0)并被编译两次,因此总编译时间约为 60-70 分钟,这大约是一半的时间。关闭一个优化功能使一个文件缩短到大约 20 秒而不是 15 分钟......这个文件正在生成一个由机器生成的函数,并且有几万行长,这导致编译器做一些魔法长的东西(大概是一些 O(N^2) 算法)。

如果您有一个小函数然后依次调用许多小函数,最终通过内联层变成一个大文件,也会发生这种情况。

在其他时候,我发现减少文件数量并将更多代码放在一个文件中效果更好。

一般来说,我的经验(无论是我自己的编译器项目,还是其他人/公司的编译器)都不是花时间解析和读取文件,而是各种优化和代码生成过程。-fsyntax-only您可以通过使用或为您的编译器调用的任何文件编译所有文件来尝试这一点。这将只是阅读源代码并检查它在语法上是否正确。-O0如果您还没有,请尝试编译。通常一个特定的优化传递是问题,并且一些传递比其他传递更差,因此检查特定-O选项中存在哪些单独的优化传递是有用的 - 在 gcc 中可以用-Q -O2 --help=optimizers[在这种情况下为-O2] 列出。

你真的需要弄清楚编译器花时间在什么上面。如果问题在于您花费大部分时间优化代码,那么更改代码是没有意义的。如果时间花在解析上,那么减少优化器是没有意义的,而优化不会增加额外的时间。如果没有实际构建您的项目,很难确定。

另一个提示是检查top你的编译进程是否每个都使用 100% cpu - 如果不是,你的编译机器可能没有足够的内存。我的工作项目有一个构建选项,它通过运行如此多的内存“杀死”我的台式机,整个系统只是停止运行——即使在网络浏览器中从一个选项卡切换到另一个选项卡也需要 15-30 秒。唯一的解决方案是少跑一些-j[当然,我通常会忘记,然后——所以如果我不想打断它,我会去吃午饭、喝咖啡或其他一些东西直到它结束,因为机器只是无法使用]。这仅适用于调试版本,因为将大型代码库的调试信息放在一起会占用大量内存 [显然!]

于 2015-07-30T21:10:31.173 回答
2

如果这种事情是罪魁祸首,那么减少编译时间的最佳做法是什么?

如果您的预处理器支持该#pragma once指令,请使用它。这将确保 .h 文件不会被多次读取。

如果没有,#include请在 .cpp 文件中使用警卫。

说你有

啊:

#ifndef A_H
#define A_H

...

#endif

您可以在 A.cpp 中使用以下方法:

#ifndef A_H
#include "A.h"
#endif

您需要为每个 .h 文件重复该模式。例如

#ifndef B_H
#include "B.h"
#endif

#ifndef C_H
#include "C.h"
#endif

您可以在What is the function of include guard in .cpp (not in .h)阅读更多关于#include在 .cpp 文件中使用警卫的信息?.

于 2015-07-30T20:45:56.003 回答
2

我不知道你是否已经这样做了,但是使用前向声明而不是在头文件中包含应该会提高编译速度。有关更多信息,请参阅此问题:

是否应该尽可能使用前向声明而不是包含?

另一种减少编译时间的方法是使用ccache. 它缓存以前编译的结果。

https://ccache.samba.org

于 2015-07-30T20:59:34.573 回答
0

将您的代码结构化为使用的PIMPL范例。两个主要好处是:

  • 您可以对用户隐藏所有实现(成员变量等)
  • 如果你改变你的实现文件,那么“一般”只有这个区域需要重新编译而不是完全重建。

有关良好的概述,请参见此处

于 2019-08-29T01:08:14.683 回答