大量的警告会增加编译时间吗?
Can a large number of warnings increase compilation time?
我听别人说,在代码中有大量警告的大项目比那些有少量警告的项目构建得要慢得多(当然,这是为了让编译器设置有高级别的警告敏感性)。
有什么合理的解释吗,或者任何人都可以分享他们关于这个话题的经验?
在GCC编译器上(例如C的gcc
或c++的g++
)警告确实占用少量CPU时间。如果想要详细的编译时间报告,可以使用gcc -ftime-report
。警告诊断依赖于优化级别。
但是优化(特别是在高层,如-O2
或更高级别)比警告花费更多的时间。根据经验,优化的编译时间与编译单元大小和最大函数的大小(例如简单指令的数量,或C代码的行数)的平方成正比。因此,如果你有庞大的函数(例如,在某些生成的C代码中,某些函数有一万行),你可能希望将它们分成更小的部分。
在MELT(一个GCC插件和GCC实验分支- gplv3 +许可-实现一个DSL来扩展GCC,我已经开发并仍在开发)的早期,它在C中生成了巨大的初始化函数(今天情况更少了,初始化被分割在许多c++函数中;参见gcc/melt/generated/warmelt-base。cc(以GCC的MELT分支为例)。当时,我绘制了编译-O2
时间与初始化函数长度的关系图,并测量了编译时间与其长度的关系。您还可以尝试使用许多dll .c代码。同样,最大函数长度的平方是一个实验性的度量,但是可以用寄存器分配问题来解释。此外,J.Pitrat还观察到,通过他有趣的CAIA系统生成的巨大的C函数正在耗尽编译器。
同时,警告也会输出,有时,如果你有很多警告,IDE或终端读取编译器输出可能会变慢。
当然,正如多次评论的那样,编译器警告是您的朋友(因此总是与例如gcc -Wall
编译)。所以请改进你的代码,使其没有任何警告。(特别是,初始化大多数局部变量——我通常初始化所有变量;因为如果可以证明一些初始化是无用的,编译器可以通过删除它们来进行优化)。
顺便说一句,你可以用例如MELT来定制GCC来添加你自己的自定义警告(例如检查一些编码规则的一致性)。
同样,在带有奇怪模板的c++中,你可能会编写几十行代码,这些代码需要花费很多时间来编译(甚至会因为内存不足而导致编译器崩溃,参见这个问题)。
NB。2019年,GCC MELT死了,它的域名gcc-melt.org
消失了,但网页在这里存档。
这在很大程度上取决于警告的实际内容。
例如,如果有很多"变量未使用"的警告和"if中的条件总是为真/假"的警告,那么这可能意味着有很多不必要的代码编译器必须解析,然后在优化过程中删除。
对于其他警告,可能有其他后果。例如,考虑由int i = i;
之类的东西引起的"变量正在自我初始化"警告。我想这可能会增加一大堆复杂性/开销(编译器试图确定变量是"活的"还是可以优化出来)。
这可能很大程度上取决于编译器,以及它是如何实现的。
话虽这么说,有两个肯定的慢速来源:
-
打印警告本身是一项重要的任务,它需要大量的格式化,可能会访问文件,加上所有这些注释(宏扩展,模板实例化),最后将其推送到I/O设备。
-
发出上述警告,以及所有这些宏扩展和模板实例化数据,可能也不是微不足道的。此外,如果首先收集并仅在编译过程结束时发出(而不是在生成它们时流式传输),那么不断增长的内存消耗也会减慢您的速度(需要操作系统提供更多的页面,…)
一般来说,就工程而言,我不希望编译器编写者过多地担心发出诊断的成本;只要成本合理,当无论如何都需要人工干预时,似乎没有什么动机去优化几毫秒。
谁在乎你的构建需要10%的时间,因为编译器打印大量的警告?问题在于你被警告的代码,而不是它所花费的额外时间。此外,对于打印甚至非常大量的警告的开销来说,10%可能是一个很大的高估。
- 使用简单类型列表实现的指数编译时间.为什么
- 在已经使用Git的情况下减少编译时间
- C++常量数组的编译时间较长
- 编译时间文本到数字转换 (atoi)
- 在C++中执行 N 阶乘编译时间的 3 种不同/相同方法
- DLLexport 类模板实例(专用化),减少了仅标头模板库的编译时间
- 替换枚举以最大化编译时间检查的最佳方法
- 不同C++功能的编译时间
- 在预编译标头中实例化模板会缩短编译时间吗?
- 使用 SCons 提取每个编译单元的编译时间
- 将 lambda 函数转换为另一个编译单元中的普通函数会缩短编译时间吗?
- std :: Invoke_result_t编译时间语法错误
- 模板;constexpr;编译时间
- 如何实现声明功能-C 11,编译时间
- 如何减少编译时间:在包含未触及的头文件的情况下
- C++编译时间类型确定
- 特征:返回对具有编译时间尺寸检查的矩阵块的引用
- 在编译时间定义多个派生类
- 在编译时间创建查找表
- C 函数在编译时间返回类型