可以使用哪些技术来加快c++编译时间?

这个问题出现在一些关于Stack Overflow问题c++编程风格的评论中,我很有兴趣听听有什么想法。

我看到过一个相关的问题,为什么c++编译要花这么长时间?,但这并没有提供很多解决方案。


当前回答

网络共享将大大降低您的构建速度,因为查找延迟很高。对于像Boost这样的东西,它给我带来了巨大的不同,尽管我们的网络共享驱动器非常快。当我从网络共享切换到本地SSD时,编译一个玩具Boost程序的时间从大约1分钟缩短到1秒。

其他回答

更快的硬盘。

编译器将许多(可能很大)文件写入磁盘。使用SSD而不是典型的硬盘,编译时间要低得多。

语言技巧

痘痘成语

看看这里和这里的impl习惯用法,也称为不透明指针或句柄类。它不仅加快了编译速度,还在与非抛出交换函数结合使用时提高了异常安全性。impl习惯用法让您减少了头文件之间的依赖关系,并减少了需要重新编译的数量。

提出声明

尽可能使用前向声明。如果编译器只需要知道SomeIdentifier是一个结构体或指针或其他什么,就不要包含整个定义,这会迫使编译器做更多的工作。这可能会产生级联效应,使这种方式比他们需要的更慢。

I/O流以降低构建速度而闻名。如果你需要它们在头文件中,尝试#包含<iosfwd>而不是<iostream>和#只在实现文件中包含<iostream>头。<iosfwd>报头只保存前向声明。不幸的是,其他标准标头没有各自的声明标头。

在函数签名中首选引用传递而不是值传递。这将消除在头文件中#include各自的类型定义的需要,您只需要向前声明类型。当然,更喜欢const引用而不是非const引用,以避免模糊的错误,但这是另一个问题。

守卫条件

使用保护条件可以防止头文件在一个翻译单元中被多次包含。

#pragma once
#ifndef filename_h
#define filename_h

// Header declarations / definitions

#endif

通过同时使用pragma和ifndef,你可以获得普通宏解决方案的可移植性,以及一些编译器在使用pragma once指令时可以实现的编译速度优化。

减少相互依存

一般来说,你的代码设计越模块化,依赖性越小,你需要重新编译的次数就越少。您还可以减少编译器同时在任何单个块上所做的工作量,因为它需要跟踪的工作量更少了。

编译器选项

预编译头文件

它们用于为多个翻译单元编译包含标题的公共部分。编译器编译它一次,并保存它的内部状态。然后可以快速加载该状态,以便在编译具有相同头集的另一个文件时抢占先机。

注意,在预编译的头文件中只包含很少更改的内容,否则您可能会更频繁地进行完全重建。这是一个存放STL头文件和其他库包含文件的好地方。

Ccache是另一个利用缓存技术来加快速度的实用程序。

使用并行性

许多编译器/ ide支持使用多个内核/ cpu同时进行编译。在GNU Make(通常与GCC一起使用)中,使用-j [N]选项。在Visual Studio中,在首选项下有一个选项,允许它并行构建多个项目。您还可以使用/MP选项进行文件级并行,而不仅仅是项目级并行。

其他并行工具:

Incredibuild 建立统一 distcc

使用较低的优化级别

编译器尝试优化的次数越多,它的工作就越困难。

共享库

将修改频率较低的代码移到库中可以减少编译时间。通过使用共享库(。或者。dll),你也可以减少链接时间。

换一台更快的电脑

更多的RAM,更快的硬盘驱动器(包括ssd),更多的cpu /内核都会使编译速度有所不同。

来自微软:https://devblogs.microsoft.com/cppblog/recommendations-to-speed-c-builds-in-visual-studio/

具体建议包括:

项目使用PCH吗 是否包含常用的系统、运行时和第三方头文件 PCH 在PCH中包含很少改变项目特定的头 不包括经常变化的头 是否定期审核PCH以保持产品流失的最新情况 使用/ mp 是否移除/Gm以支持/MP 是否解决与#import和use /MP的冲突 是否使用连接器开关/增量 使用链接器开关/调试:fastlink 是否考虑使用第三方构建加速器

你可以使用Unity Builds。

​​

虽然不是一个“技术”,我不知道Win32项目与许多源文件编译速度比我的“Hello World”空项目。因此,我希望这能帮助到像我这样的人。

在Visual Studio中,增加编译时间的一个选项是增量链接(/ Incremental)。它与链接时代码生成(/LTCG)不兼容,因此在进行版本构建时请记住禁用增量链接。