长时间编译是否已成为历史?


38

关于编译需要多长时间的战争故事不计其数。甚至xkcd都提到了它。

现在,我已经有很长时间没有编程了,并且几乎只接触过Java和Python(Python是一种解释性语言,而不是一种编译语言)。我意识到有可能我只是没有遇到过需要很长时间才能编译的项目,但是即使对于像样的应用程序,它对我来说是瞬时的(通常由IDE在后台处理)或花费不超过30个一个非常大的项目大约需要几秒钟。即使在商业环境中(发生漫画的地方),我也从来没有花太多时间来编译代码。

我只是没有接触过编译时间长的项目吗?这是过去的遗物,不再是现代发生的事情吗?为什么编译需要这么长时间?


31
尝试编译铬。
UldisK 2014年

2
获取Linux内核的副本。做一个完整的构建。你自己看。或者,如果您是Java编码员,请从源头获取Spring。实际上,此问题有几个答案,就像在投票中一样(“我已经完成30分钟的编译...”类型的答案),可以回答该问题,这表明该问题本身并不适合。

最近的一个大型项目花了我40分钟的时间进行编译(使用Maven编译了4万个源代码文件)。解决方法是使许多CPU内核上的编译无效。
Niklas Rosencrantz 2014年

2
选择一个源Linux发行版(gentoo,LFS等),然后花几天时间编译要安装的每个软件。
Basile Starynkevitch 2014年

6
定义长时间...对于一个刚从学校毕业的孩子来说,一分钟可能看起来很长,对于一个已经在战trench里呆了几十个小时的老朋友来说,这简直不容小eye。
jwenting 2014年

Answers:


48

编译可能需要一段时间,尤其是对于使用C,C ++或Scala等语言编写的大型项目。在后台编译部件可以减少编译时间,但是有时您必须重新进行编译。可能导致较长编译时间的因素包括:

  • 很明显,代码量很大。大型项目将包含数十万行代码。

  • C的#include预处理程序指令,该指令有效地导致同一代码被编译数百次。宏系统在文本级别上工作时也有类似的问题。预处理器确实会使实际传递给编译器的代码大小膨胀。预处理后(例如通过gcc -E)查看文件应该可以睁开眼睛。

  • C ++的模板是Turing完整的,这意味着从理论上讲,您可以在编译时执行任意计算。没有人真的想要这样做,但是即使很多简单的案例也确实花费了很多时间来专门化模板。

  • Scala是一门相当年轻的语言,编译器的优化不足。当前,编译器使用大量编译通道(C设计为仅需要两次编译通道)。类型检查是其中的一种方式,由于该语言具有复杂的类型系统,因此可能要花费一些时间。

编译不是唯一需要时间的事情。编译项目后,应运行测试套件。花费的时间可能在几秒钟到几个小时不等(如果测试写得不好)。


14
实际上,Scala的类型系统是图灵完备的,因此类型检查可能会花费无数的时间,并且编译器无法确定。
约尔格W¯¯米塔格

7
不要忘记优化。(例如)C / C ++编译器将要进行的许多优化工作非常昂贵(例如,过于昂贵以至于JIT根本无法负担它们)。在最坏的情况下,大多数工具链现在都支持整个程序的优化,这众所周知会大大增加构建时间。
布伦丹2014年

我接受了这个答案,因为您指出了我没有考虑的许多事情,特别是将整个过程编译成分段而不是逐个进行编译,并且事实是测试套件可能包含在“编译”时。
Thunderforge 2014年

1
不仅仅是测试套件-代码覆盖率分析,自动打包,自动部署到测试系统;如今,有很多东西被打包到一个集成的构建系统中。而且,如果您在进入开发人员或质量保证环境之前一直处于等待状态,那么您当然有时间进行一些小技巧。
corsiKa 2014年

1
很好的答案,我只想指出,可能的编译时间跨度可能会更大。我从事的项目可能需要两到三天才能完成一次完整的编译(是的,这太可怕了!),我想那里还有更糟糕的违规者。
罗伊(Roy T.)

17

这绝不是过去的遗物。我从事的项目之一需要45分钟才能从头开始进行完整构建。除了我们自己的代码,我们还必须从外部存储库中的几个大型C和C ++库中提取并构建源代码。编译和链接C和C ++代码的计算量很大。如您所指出的那样,Python通常被实现为一种解释语言,而Java通常使用JIT(Just in Time)编译器,因此您的项目将跳过前期编译并完全链接成本。您所付出的代价是启动时间更长,并且(至少对于Python而言)执行速度较慢。

当构建时间过长时,利用诸如JenkinsTeamCity之类的持续集成系统变得更加重要。这使单个开发人员可以(大部分)避免从头开始构建的痛苦,同时仍在测试更改不会破坏构建。


1
javac不会“完全跳过前期编译并完全链接成本 ”。它跳过了很多优化成本,但仍在将源代码转换为字节码,并在此过程中进行了大量静态检查。它所做的与C编译器一样多的链接。真正的性能差异是Java的编译过程是在一个时代设计的,该时代被认为可以将整个程序及其依赖项立即加载到内存中,而不必将其分解成很小的块并重复处理数千次相同的文件。
彼得·泰勒

10

大型项目可能需要很长时间。一个足够大的项目可能需要一个小时或更长时间。我必须从计算机上的源代码中编译几个库,这些库需要很长时间-例如opencascade。如果必须从头开始构建,Linux内核本身也需要花费很长时间。

但是,还有其他类似编译的过程可能需要更长的时间。数字电路设计(针对ASIC或FPGA)需要放置和布线步骤。布局和布线步骤是确定各个逻辑门,触发器,寄存器,RAM和其他组件的布局以及互连布线的布局。该软件使用时序模型来确定可能放置的选通和布线延迟,将其与时序约束所提供的限制进行比较,然后调整放置位置和布线路径以尝试满足时序要求。有时,该软件甚至不得不调整门的大小并添加缓冲区以满足时序要求。此步骤的计算量很大,可能需要数小时甚至数天才能完成。它也并不能很好地并行化。我大约一年前就在做一个FPGA设计,它消耗了大约一半的Virtex 6 HXT 565 FPGA(在565k个LUT中约占300k),并花费了大约7个小时来完成布局和布线。我无法想象在Core i7 CPU设计之类的产品上放置和布线需要多长时间-可能至少需要几周。


4

其他答案已经提到,是的,大型项目中的代码意味着50万行及以上,可能会花费大量时间,尤其是从头开始构建时。

另外一点是,必须为多个目标环境构建某些项目。当承载这些环境的计算机不可用时,必须通过交叉编译在您拥有的计算机上串行进行构建。这会导致大量的构建时间。对于我从事的一个项目,每晚构建将花费10个小时。不幸的是,您是打破它的人!

我要补充一点,您不会因此浪费时间。一个专业的人应该规划自己的工作,这样他们拥有有用的这样的时期做一些事情。


3

两者都有。C ++(以及程度较小的C)因编译时间较慢而臭名昭著,尤其是在定期硬件上。在千年之交的时候,由于宏观因素,我从事了一个耗时约4个小时的项目。

如今,情况有所改善,但我的经验不足30秒-尤其是在正式构建中,需要从源代码管理中检查事物,运行单元测试,构建安装程序并将所有内容发送到某个地方的SAN。


2

它取决于项目及其编译环境。我从事的C ++项目需要花几分钟的时间进行编译(在MSVS中设置为多个项目),这可能是剑拔enough张的时间。

如果您为拥有巨大代码和数据库的大型公司(Proctor和Gamble,Google等)工作,或者为小型公司或初创公司工作,而这些公司专注于一种或两种非常复杂的主要产品(例如科学模拟和渲染),那么即使在功能强大的机器上,等待大型项目进行编译也是一件现实的事情。这可能会影响您开发和调试代码的方式(以及选择通过版本控制更新和合并更改的频率)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.