简体   繁体   English

GCC/Make 构建时间优化

[英]GCC/Make Build Time Optimizations

We have project which uses gcc and make files.我们有使用 gcc 并制作文件的项目。 Project also contains of one big subproject (SDK) and a lot of relatively small subprojects which use that SDK and some shared framework.项目还包含一个大子项目 (SDK) 和许多使用 SDK 和一些共享框架的相对较小的子项目。

We use precompiled headers, but that helps only for re-compilation to be faster.我们使用预编译的头文件,但这仅有助于重新编译更快。

Is there any known techniques and tools to help with build-time optimizations?是否有任何已知的技术和工具可以帮助进行构建时优化? Or maybe you know some articles/resources about this or related topics?或者,也许你知道一些关于这个或相关主题的文章/资源?

You can tackle the problem from two sides: refactor the code to reduce the complexity the compiler is seeing, or speed up the compiler execution.您可以从两个方面解决这个问题:重构代码以降低编译器看到的复杂性,或者加快编译器的执行速度。

Without touching the code, you can add more compilation power into it.无需接触代码,您就可以在其中添加更多的编译能力。 Use ccache to avoid recompiling files you have already compiled and distcc to distribute the build time among more machines.使用 ccache 避免重新编译您已经编译的文件,并使用 distcc 在更多机器之间分配构建时间。 Use make -j where N is the number of cores+1 if you compile locally, or a bigger number for distributed builds.使用 make -j 其中 N 是内核数+1,如果你在本地编译,或者更大的数字用于分布式构建。 That flag will run more than one compiler in parallel.该标志将并行运行多个编译器。

Refactoring the code.重构代码。 Prefer forward declaration to includes (simple).更喜欢前向声明而不是包含(简单)。 Decouple as much as you can to avoid dependencies (use the PIMPL idiom).尽可能多地解耦以避免依赖(使用 PIMPL 习惯用法)。

Template instantiation is expensive, they are recompiled in every compilation unit that uses them.模板实例化很昂贵,它们在每个使用它们的编译单元中重新编译。 If you can refactor your templates as to forward declare them and then instantiate them in only one compilation unit.如果您可以重构模板以转发声明它们,然后仅在一个编译单元中实例化它们。

The best I can think of with make is the -j option.我能想到的最好的make-j选项。 This tells make to run as many jobs as possible in parallel:这告诉make并行运行尽可能多的作业:

make -j

If you want to limit the number of concurrent jobs to n you can use:如果要将并发作业的数量限制为n ,可以使用:

make -j n make -j n


Make sure the dependencies are correct so make doesn't run jobs it doesn't have to.确保依赖项是正确的,这样make就不会运行它不需要的作业。


Another thing to take into account is optimizations that gcc does with the -O switch.另一件需要考虑的事情是gcc-O开关所做的优化。 You can specify various levels of optimization.您可以指定各种优化级别。 The higher the optimization, the longer the compile and link times.优化程度越高,编译和链接时间越长。 A project I work with runs takes 2 minutes to link with -O3 , and half a minute with -O1 .我使用的一个项目需要 2 分钟才能与-O3链接,半分钟与-O1链接。 You should make sure you're not optimizing more than you need to.您应该确保您的优化没有超出您的需要。 You could build without optimization for development builds and with optimization for deployment builds.您可以在不优化开发构建和优化部署构建的情况下构建。


Compiling with debug info ( gcc -g ) will probably increase the size of your executable and may impact your build time.使用调试信息 ( gcc -g ) 进行编译可能会增加可执行文件的大小并可能影响构建时间。 If you don't need it, try removing it to see if it affects you.如果您不需要它,请尝试删除它以查看它是否会影响您。


The type of linking (static vs. dynamic) should make a difference.链接的类型(静态与动态)应该有所不同。 As far as I understand static linking takes longer (though I may be wrong here).据我了解 static 链接需要更长的时间(尽管我在这里可能错了)。 You should see if this affects your build.您应该看看这是否会影响您的构建。

From the description of the project I guess that you have one Makefile per directory and are using recursive make a lot.从项目的描述中,我猜你每个目录都有一个 Makefile 并且经常使用递归。 In that case techniques from "Recursive Make Considered Harmful" should help very much.在这种情况下, “Recursive Make Considered Harmful”中的技术应该会很有帮助。

If you have multiple computers available gcc is well distributed by distcc .如果您有多台计算机可用 gcc 由distcc很好地分发。

You can also use ccache in addition.此外,您还可以使用ccache

All this works with very little changes of the makefiles.所有这些都只需要对 makefile 进行很少的更改即可。

Also, you'll probably want to keep your source code files as small and self-contained as possible/feasible, ie prefer many smaller object files over one huge single object file.此外,您可能希望使您的源代码文件尽可能小且独立/可行,即更喜欢许多较小的 object 文件而不是一个巨大的单个 object 文件。

This will also help avoid unnecessary recompilations, in addition you can have one static library with object files for each source code directory or module, basically allowing the compiler to reuse as much previously compiled code as possible.这也将有助于避免不必要的重新编译,此外,您可以为每个源代码目录或模块拥有一个 object 文件的 static 库,基本上允许编译器尽可能多地重用以前编译的代码。

Something else, which wasn't yet mentioned in any of the previous responses, is making symbol linkage as 'private' as possible, ie prefer static linkage (functions, variables) for your code if it doesn't have to be visible externally.之前的任何回复中尚未提及的其他内容正在使符号链接尽可能“私有”,即,如果您的代码不必在外部可见,则更喜欢 static 链接(函数、变量)。

In addition, you may also want to look into using the GNU gold linker , which is much more efficient for compiling C++ code for ELF targets.此外,您可能还想研究使用GNU gold linker ,这对于为 ELF 目标编译 C++ 代码效率更高

Basically, I'd advise you to carefully profile your build process and check where the most time is spend, that'll give you some hints as to how to optimize your build process or your projects source code structure.基本上,我建议您仔细分析构建过程并检查花费最多的时间,这将为您提供一些关于如何优化构建过程或项目源代码结构的提示。

You could consider switching to a different build system (which obviously won't work for everyone), such as SCons.您可以考虑切换到不同的构建系统(显然不适用于所有人),例如 SCons。 SCons is much smarter than make. SCons 比 make 聪明得多。 It automatically scans header dependencies, so you always have the smallest set of rebuild dependencies.它会自动扫描 header 依赖项,因此您始终拥有最小的重建依赖项集。 By adding the line Decider('MD5-timestamp') to your SConstruct file, SCons will first look at the time stamp of a file, and if it's newer than the previously built time stamp, it will use the MD5 of the file to make sure you actually changed something.通过在 SConstruct 文件中添加Decider('MD5-timestamp')行,SCons 将首先查看文件的时间戳,如果它比之前构建的时间戳更新,它将使用文件的 MD5 来制作确定你确实改变了一些东西。 This works not just on source files but object files as well.这不仅适用于源文件,也适用于 object 文件。 This means that if you change a comment, for instance, you don't have to re-link.这意味着如果您更改评论,例如,您不必重新链接。

The automatic scanning of header files has also ensured that I never have to type scons --clean. header 文件的自动扫描还确保我永远不必键入 scons --clean。 It always does the right thing.它总是做正确的事。

Using small files may not always be a good recommendation.使用小文件可能并不总是一个好的建议。 A disk have a 32 or 64K min sector size, with a file taking at least a sector.磁盘的最小扇区大小为 32 或 64K,文件至少占用一个扇区。 So 1024 files of 3K size (small code inside) will actually take 32 or 64 Meg on disk, instead of the expected 3 meg.所以 1024 个 3K 大小的文件(内部的小代码)实际上会占用 32 或 64 Meg 的磁盘空间,而不是预期的 3 meg。 32/64 meg that needs to be read by the drive.需要由驱动器读取的 32/64 meg。 If files are dispersed around on the disk you increase read time even more with seek time.如果文件分散在磁盘上,则寻道时间会增加读取时间。 This is helped with Disk Cache obviously, to a limit.显然,这对磁盘缓存有一定的帮助。 pre-compiled header can also be of good help alleviating this.预编译的 header 也可以很好地帮助缓解这种情况。

So with due respect to coding guidelines, there is no point in going out of them just to place each strcuct, typedef or utility class into separate files.因此,考虑到编码指南,将每个结构、类型定义或实用程序 class 放入单独的文件中是没有意义的。

You can use distcc distributed compiler to reduce the build time if you have access to several machines.如果您可以访问多台机器,则可以使用distcc分布式编译器来减少构建时间。 Here's an article from from IBM developerWorks related to distcc and how you can use it: http://www.ibm.com/developerworks/linux/library/l-distcc.html这是来自 IBM developerWorks 的一篇与 distcc 相关的文章以及如何使用它: http://www.ibm.com/developerworks/linux/library/l-distcc.html

Another method to reduce build time is to use precompiled headers.另一种减少构建时间的方法是使用预编译头文件。 Here's a starting point for gcc .这是gcc 的起点

Also don't forget to use -j when building with make if your machine has more than one cpu/core(2x the number of cores/cpus is just fine).如果您的机器有多个 cpu/core(2x cores/cpus 的数量就可以了),也不要忘记在使用 make 构建时使用 -j。

If you have a LAN with developer machines, perhaps you should try implementing a distributed compiler solution, such as distcc .如果您有一个带有开发人员机器的 LAN,也许您应该尝试实现一个分布式编译器解决方案,例如distcc

This might not help if all of the time during the build is spent analyzing dependencies, or doing some single serial task.如果构建过程中的所有时间都花在分析依赖关系或执行一些单一的串行任务上,这可能无济于事。 For the raw crunch of compiling many source files into object files, parallel building obviously helps, as suggested (on a single machine) by Nathan.对于将许多源文件编译成 object 文件的原始紧缩,并行构建显然有帮助,正如 Nathan 建议的(在单台机器上)。 Parallelizing across multiple machines can take it even further.跨多台机器并行化可以更进一步。

http://ccache.samba.org/ speeds up big time. http://ccache.samba.org/ 大大加快了速度。

I work on a middle sized project, and that's the only thing we do to speed up the compile time.我从事一个中等规模的项目,这是我们加快编译时间的唯一方法。

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

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