【发布时间】:2016-08-11 14:20:45
【问题描述】:
代码合并是将整个源代码复制到一个文件中。
例如,SQLite 可以减少编译时间并提高生成的可执行文件的性能。在这里,它产生了一个包含 184K 行代码的文件。
我的问题不是关于编译时间(已经在this question 中回答),而是关于可执行文件的效率。
SQLite 开发者说:
除了让 SQLite 更容易整合到其他项目中之外,合并还使它运行得更快。当代码包含在单个翻译单元中(例如合并中)时,许多编译器能够对代码进行额外的优化。当我们使用合并来编译 SQLite 而不是单独的源文件时,我们测量到了 5% 到 10% 的性能改进。这样做的缺点是额外的优化通常采用函数内联的形式,这往往会使生成的二进制图像的大小更大。
据我了解,这是由于interprocedural optimization (IPO),编译器进行的优化。
GCC 开发者也这么说(感谢@nwp 提供链接):
编译器根据它对程序的了解执行优化。一次将多个文件编译为单个输出文件模式允许编译器在编译每个文件时使用从所有文件中获取的信息。
但他们没有谈论最终的收获。
除了 SQLite 的那些测量之外,是否有任何测量证实或反驳 IPO with amalgamation 在使用 gcc 编译时比 IPO without amalgamation 产生更快的可执行文件的说法?
作为一个附带问题,关于此优化,进行代码合并或将所有 .cpp(或 .c)文件#include 到一个文件中是否相同?
【问题讨论】:
-
哦,这是一个讨论式的问题。它不适合这个网站。
-
编译速度优势值得怀疑,因为您不能进行增量构建。如果工具链允许良好的链接时优化,编译的结果也不一定要好得多。
-
@Olaf 这里“C/C++”的意思是“C 或C++ 语言”,而不是“C/C++ 语言”。根据您的说法,哪个网站更适合此类问题?由于已经有相关问题,我认为这是一个不错的网站。
-
您提到的缺点也适用于多文件源分发(A 必须重新编译 + 发布以合并 B 的新版本)。作为“A”应用程序创建者,您通常对部署环境几乎没有控制权,因此您要么制作一个非常聪明的安装程序来处理依赖项并根据需要安装额外的软件(Linux 软件包管理器,如 Debian 上的
dpkg),要么您必须将所有内容与“A”一起分发。编译时依赖和捆绑依赖之间的区别在于,通过安装第一个依赖,您可以减少对主机的污染并减少冲突的风险。 -
在寻找一种工具来为库创建头文件的合并时看到了这一点。我对性能优势不感兴趣;只是包含文件的可移植性。 100% 正确,至少在较旧的 C++ 编译器中,如果您创建了一个合并,您可以获得更优化的代码。为什么必须在使用函数之前声明它们?较新的编译器/生成器,不需要您声明函数,如 C#,可能会获得较少的好处。但是,他们在构建时对您的源进行了两次传递。今天,这个问题可能比实际更学术。
标签: c++ c gcc compiler-optimization