我从某人那里听说,代码构建中出现大量警告的大型项目明显慢于那些警告少的项目(当然,编译器设置为具有高级警告敏感性)。
是否有任何合理的解释,或者任何人都可以分享他们对此主题的经验?
答案 0 :(得分:8)
在GCC编译器上(例如,gcc
表示C或g++
表示C ++)警告确实占用了少量的CPU时间。使用例如gcc -ftime-report
如果您想要详细报告编译器时序。警告诊断取决于优化级别。
但优化(特别是在高级别,如-O2
或更多)比警告花费更多时间。根据经验,优化的编译时间与编译单元大小和最大函数的大小(例如,Gimple指令的数量或C代码行的 square )成比例。因此,如果你有很多函数(例如某些生成的C代码中有一万行的函数),你可能希望将它们分成更小的部分。
早期MELT(GCC插件和GCC实验分支-GPLv3 +许可 - 实施DSL扩展GCC,我已经开发并且仍在继续工作),它在C中生成了巨大的初始化函数(现在情况不同,初始化在许多C ++函数中被分割;例如,参见GCC的MELT分支中的gcc/melt/generated/warmelt-base.cc)。那时,我绘制了编译-O2
时间与初始化函数的长度,并测量了编译时间与其长度的关系。您还可以尝试使用manydl.c代码。同样,最大函数长度的平方是一个实验测量,但可能由寄存器分配问题来解释。此外,J.Pitrat还观察到巨大的C函数 - 通过他有趣的CAIA系统 - 正在耗尽编译器。
此外,还会输出警告,有时,如果您收到很多警告,IDE或读取编译器输出的终端可能会变慢。
当然,经过多次评论,编译器警告是你的朋友(所以始终使用例如gcc -Wall
进行编译)。所以请改进您的代码以获取任何警告。 (特别是,初始化大多数局部变量 - 我通常会初始化所有这些变量;因为如果可以证明它们没用,编译器可以通过删除一些初始化来优化。)
顺便说一句,您可以使用例如自定义GCC。 MELT添加您自己的自定义警告(例如,检查某些编码规则的一致性)。
此外,在使用奇怪模板的C ++中,您可以编写几十行,这些行需要花费数小时才能编译(或者由于内存不足而导致编译器崩溃,请参阅this question)。
NB。 2019年,GCC MELT已经死亡,其域名gcc-melt.org
消失,但网页已归档here。
答案 1 :(得分:3)
这在很大程度上取决于警告实际上是什么。
例如,如果有很多"变量未使用"警告和"条件在'如果'永远是真/假"警告,那么这可能意味着编译器必须解析许多不必要的代码,然后在优化过程中将其删除。
对于其他警告,可能还有其他后果。例如,考虑一个"变量是自我初始化"由int i = i;
之类的警告引起的警告。我想象这可能会增加一大堆复杂性/开销(编译器试图确定变量是否为"生存"或者可以优化)。
答案 2 :(得分:2)
这很可能在很大程度上取决于编译器及其实现方式。
话虽如此,有两个确定的减速来源:
打印警告本身是一项非常重要的任务,它需要大量格式化,可能会访问文件,加上所有这些注释(宏扩展,模板实例化),最后将其推送到I / O设备
使用所有宏扩展和模板实例化数据发出所述警告也可能是非平凡的。此外,如果首先收集并且仅在编译过程结束时发出(而不是在生成时进行流式传输),那么不断增长的内存消耗也会降低您的速度(需要操作系统提供更多页面,... )
一般来说,在工程方面,我不认为编译器编写者会担心发出诊断的成本;只要这是一个合理的成本,当需要进行人工干预时,似乎没有什么动力去优化几毫秒。
答案 3 :(得分:1)
由于编译器打印了大量警告,谁会关心你的构建需要10%的时间?问题是你被警告的代码,而不是额外的时间。此外,对于打印甚至大量警告的开销,10%可能是一个巨大的高估。