什么可以编译得更快?每种方法的源代码和标头,还是单个文件中的任何内容?
Posted
技术标签:
【中文标题】什么可以编译得更快?每种方法的源代码和标头,还是单个文件中的任何内容?【英文标题】:What can be compiled faster? Source and header for each method, or anything in one single file? 【发布时间】:2015-05-10 18:23:57 【问题描述】:我正在编写一个最后生成 C++ 代码的编译器。我目前想知道什么编译速度更快。
关于编译器的第一个注意事项:
-
我没有任何类\结构,它们在函数内部进行了优化。
我不包括像
#include <vector>
这样的东西,当我必须使用库中的printf
等函数时,我手动放置原型。 (编译器手动完成。)
我有两个选择:
选项#1:
//.h
#include "A.h"
#include "B.h"
int function( /* parameters */ );
//.cpp
int function( /* parameters */ )
// code
每个函数都有它自己的源代码和头文件。 优点:
-
我可以让编译器注释掉包含在它之前包含的文件的包含。例如,如果
#include "B.h"
的内容包含在#include "A.h"
中,那么我可以让它注释掉#include "B.h"
行。 (保存文件读取。)
我可以识别未更改的方法/函数/文件(当我重新生成我的代码时,它可以找到以前的确切文件。)并回收它们的目标文件。 (保存对象编译。)
选项 #2:
int function( /* parameters */ );
int function2( /* parameters */ );
int function3( /* parameters */ );
// ...
int function( /* parameters */ )
// code
// ...
所有函数都定义一次(顶部的原型)并在该单个文件中编译。
优点:
-
从磁盘进行单次顺序读取。 (没有来自不同对象的包含和多重包含的层次结构。)
要编译的单个对象,不包括库。
乍一看,选项 #1 似乎更快,但有些人说他们尝试了第二个,这让他们的项目在编译时间上得到了提升。他们没有比较这两种选择,也没有提供任何证据。
我能解释一下哪个更快而不是基准测试吗?
【问题讨论】:
基准测试并找出答案。其他任何事情都主要是猜测。 @ColonelThirtyTwo 我相信有人可以“给出意见”,但为什么选项比另一个更快,而不仅仅是基准测试。 选项3:实现modules @Bolov:你可能是对的,但它还不是标准 C++ @LyingOnTheSky:如果您使用 C 标头中的函数,至少包括 C 标头。自己宣布这些东西是毁灭之路。 【参考方案1】:最重要的因素之一是并行编译的能力。由于每个翻译单元都是按顺序编译的(至少在逻辑上),如果您只为 C++ 编译器提供一个大文件,则并行化的机会有限。
正如所指出的,平衡力是每次编译的启动成本。您有多个 CPU 内核会产生相同的启动成本。
因此,当添加额外的翻译单元所产生的间接成本比使用额外内核节省的更多时,并行化不再是一种胜利。
【讨论】:
但是在那之后你必须链接所有你编译的对象,这是你不能并行的。我认为一个大对象将使链接更快。 (?) 我开始认为只有基准测试才有帮助。 @LyingOnTheSky:现代链接器无论如何都使用函数级链接,一个大对象仍然包含尽可能多的函数。【参考方案2】:众所周知,C++ 的编译速度很慢,特别是因为标准 C++ 头文件(例如 <vector>
、<map>
或其他标准容器)带来了很多的 C++ 代码(和令牌)通过内部标头。
您的#include
-d 标头是机器生成的,还是它们都对您的运行时通用?您可能会考虑使用 single 标头并预编译它(假设 recent GCC 或 Clang/LLVM 编译器),请参阅 this。那么你只需要在每个生成的 C++ 文件的顶部有一个 #include
。
顺便说一句,我不确定 C++ 是否适合某些编译器的目标语言。生成 C 代码(可能使用 Boehm's GC,就像 Bigloo 一样)可能更相关。当你想适应一些现有的 API 时,生成 C++ 代码是有意义的,就像我在 MELT 中所做的那样适应 GCC 内部,然后我不会使用 C++ 标准模板生成太多代码。
最后,当您生成 C 时(甚至在生成 genuine C++ 时更是如此),您真的希望 C 或 C++ 编译器优化生成的 C 或 C++ 代码。生成代码的解析时间并不重要(您可以尝试-ftime-report 选项来衡量g++
花费时间的位置)。最新的 GCC 5.1 有 libgccjit 你可能会感兴趣。
【讨论】:
它仍然会消除跨不同.cpp
s 重新包含标题,但它不会消除链接大量对象的需要。以上是关于什么可以编译得更快?每种方法的源代码和标头,还是单个文件中的任何内容?的主要内容,如果未能解决你的问题,请参考以下文章
如果我用 codeBlocks 编译它,为啥我的代码运行得更快
为啥很少有人输入 const 正确的代码? const 正确的代码会编译得更好/更快吗? [关闭]