繁体   English   中英

GCC/Make 构建时间优化

[英]GCC/Make Build Time Optimizations

我们有使用 gcc 并制作文件的项目。 项目还包含一个大子项目 (SDK) 和许多使用 SDK 和一些共享框架的相对较小的子项目。

我们使用预编译的头文件,但这仅有助于重新编译更快。

是否有任何已知的技术和工具可以帮助进行构建时优化? 或者,也许你知道一些关于这个或相关主题的文章/资源?

您可以从两个方面解决这个问题:重构代码以降低编译器看到的复杂性,或者加快编译器的执行速度。

无需接触代码,您就可以在其中添加更多的编译能力。 使用 ccache 避免重新编译您已经编译的文件,并使用 distcc 在更多机器之间分配构建时间。 使用 make -j 其中 N 是内核数+1,如果你在本地编译,或者更大的数字用于分布式构建。 该标志将并行运行多个编译器。

重构代码。 更喜欢前向声明而不是包含(简单)。 尽可能多地解耦以避免依赖(使用 PIMPL 习惯用法)。

模板实例化很昂贵,它们在每个使用它们的编译单元中重新编译。 如果您可以重构模板以转发声明它们,然后仅在一个编译单元中实例化它们。

我能想到的最好的make-j选项。 这告诉make并行运行尽可能多的作业:

make -j

如果要将并发作业的数量限制为n ,可以使用:

make -j n


确保依赖项是正确的,这样make就不会运行它不需要的作业。


另一件需要考虑的事情是gcc-O开关所做的优化。 您可以指定各种优化级别。 优化程度越高,编译和链接时间越长。 我使用的一个项目需要 2 分钟才能与-O3链接,半分钟与-O1链接。 您应该确保您的优化没有超出您的需要。 您可以在不优化开发构建和优化部署构建的情况下构建。


使用调试信息 ( gcc -g ) 进行编译可能会增加可执行文件的大小并可能影响构建时间。 如果您不需要它,请尝试删除它以查看它是否会影响您。


链接的类型(静态与动态)应该有所不同。 据我了解 static 链接需要更长的时间(尽管我在这里可能错了)。 您应该看看这是否会影响您的构建。

从项目的描述中,我猜你每个目录都有一个 Makefile 并且经常使用递归。 在这种情况下, “Recursive Make Considered Harmful”中的技术应该会很有帮助。

如果您有多台计算机可用 gcc 由distcc很好地分发。

此外,您还可以使用ccache

所有这些都只需要对 makefile 进行很少的更改即可。

此外,您可能希望使您的源代码文件尽可能小且独立/可行,即更喜欢许多较小的 object 文件而不是一个巨大的单个 object 文件。

这也将有助于避免不必要的重新编译,此外,您可以为每个源代码目录或模块拥有一个 object 文件的 static 库,基本上允许编译器尽可能多地重用以前编译的代码。

之前的任何回复中尚未提及的其他内容正在使符号链接尽可能“私有”,即,如果您的代码不必在外部可见,则更喜欢 static 链接(函数、变量)。

此外,您可能还想研究使用GNU gold linker ,这对于为 ELF 目标编译 C++ 代码效率更高

基本上,我建议您仔细分析构建过程并检查花费最多的时间,这将为您提供一些关于如何优化构建过程或项目源代码结构的提示。

您可以考虑切换到不同的构建系统(显然不适用于所有人),例如 SCons。 SCons 比 make 聪明得多。 它会自动扫描 header 依赖项,因此您始终拥有最小的重建依赖项集。 通过在 SConstruct 文件中添加Decider('MD5-timestamp')行,SCons 将首先查看文件的时间戳,如果它比之前构建的时间戳更新,它将使用文件的 MD5 来制作确定你确实改变了一些东西。 这不仅适用于源文件,也适用于 object 文件。 这意味着如果您更改评论,例如,您不必重新链接。

header 文件的自动扫描还确保我永远不必键入 scons --clean。 它总是做正确的事。

使用小文件可能并不总是一个好的建议。 磁盘的最小扇区大小为 32 或 64K,文件至少占用一个扇区。 所以 1024 个 3K 大小的文件(内部的小代码)实际上会占用 32 或 64 Meg 的磁盘空间,而不是预期的 3 meg。 需要由驱动器读取的 32/64 meg。 如果文件分散在磁盘上,则寻道时间会增加读取时间。 显然,这对磁盘缓存有一定的帮助。 预编译的 header 也可以很好地帮助缓解这种情况。

因此,考虑到编码指南,将每个结构、类型定义或实用程序 class 放入单独的文件中是没有意义的。

如果您可以访问多台机器,则可以使用distcc分布式编译器来减少构建时间。 这是来自 IBM developerWorks 的一篇与 distcc 相关的文章以及如何使用它: http://www.ibm.com/developerworks/linux/library/l-distcc.html

另一种减少构建时间的方法是使用预编译头文件。 这是gcc 的起点

如果您的机器有多个 cpu/core(2x cores/cpus 的数量就可以了),也不要忘记在使用 make 构建时使用 -j。

如果您有一个带有开发人员机器的 LAN,也许您应该尝试实现一个分布式编译器解决方案,例如distcc

如果构建过程中的所有时间都花在分析依赖关系或执行一些单一的串行任务上,这可能无济于事。 对于将许多源文件编译成 object 文件的原始紧缩,并行构建显然有帮助,正如 Nathan 建议的(在单台机器上)。 跨多台机器并行化可以更进一步。

http://ccache.samba.org/ 大大加快了速度。

我从事一个中等规模的项目,这是我们加快编译时间的唯一方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM