是什么让Java编译器如此之快?

时间:2008-12-31 13:39:26

标签: c# java .net c++ compiler-construction

我想知道是什么让主编译器(sun的javac)在编译时如此快?

..以及Microsoft的C#.NET编译器。

我将它们与C ++编译器(例如G ++)进行比较,所以也许我的问题应该是,是什么让C ++编译器变得如此缓慢:)

11 个答案:

答案 0 :(得分:16)

这个问题很好地回答了这个问题:Why does C++ compilation take so long?(正如jalf在评论部分指出的那样)

基本上它是C ++缺少的模块概念,以及编译器完成的积极优化。

答案 1 :(得分:6)

我认为最困难的部分不是需要编译头文件(除非它们非常大,但在这种情况下你可以使用预编译头文件)。最糟糕的部分始终是C ++的语法对语境过于敏感。尽管我喜欢C ++,但我为任何必须编写C ++解析器的人感到遗憾。

答案 2 :(得分:5)

有几件事使C ++编译器比Java / C#慢。语法要复杂得多,通用编程支持在C ++中更强大,但同时编译起来更加昂贵。包含文件的方式与导入模块的方式不同。

包含头文件

首先,每当你在C ++中包含一个文件时,文件的内容(通常为.h)都会注入当前的编译单元(包括防护,避免重新注入相同的头两次),这是可传递的。也就是说,如果你包含头a.h,它又包含b.h,你的编译单元将包含a.h中的所有代码和b.h中的所有代码。

Java(或C#,我将谈论Java,但它们在此类似)没有包含文件,它们依赖于编译所用类的二进制文件。这意味着无论何时编译使用b.java中定义的对象B的a.java,它只检查二进制b.class,它不需要更深入地检查B的依赖关系,因此它可以更早地切断进程(只有一个级别的检查)。

同时,包含文件只包含语言定义,处理它需要时间。当Java / C#编译器读取二进制文件时,它具有相同的信息,但已经由生成它的编译步骤处理。

所以最后,在C / C ++中包含了更多的文件,同时处理这些包含比处理二进制模块更昂贵。

<强>模板

模板以他们自己的方式是特殊的。它们可以预编译,但通常不会(出于一系列原因)。这意味着在使用std :: vector的所有编译单元中,处理使用的整个向量方法集(未使用的模板方法不被编译),并且编译器生成二进制代码。在稍后的步骤中,在链接期间,同一方法的冗余定义将被删除,但在编译期间,它们必须被处理。

Java中对泛型的支持在很多方面受到更多限制。最后,例如,只有一个Vector类二进制文件,每当编译器在java中看到Vector时,它所做的就是在委托给真正的Vector实现(存储普通对象)之前生成类型检查代码,这不是通用的。编译器确实提供类型保证,但不为每种类型编译Vector。

在C#中,它再一次是不同的。对泛型的C#支持比Java更复杂,最后泛型类与普通类不同,但无论如何它们只编译一次,因为二进制格式具有所有必需的信息。

答案 3 :(得分:3)

因为它们做了一些完全不同的事情,C ++编译器产生优化的本机代码,而C#,VB .Net和Java编译器产生的中间语言比你第一次执行应用程序时变成本机代码,这就是你加载缓慢的原因第一次执行应用程序时在Java等应用程序中的应用程序。

在执行应用程序时,C ++编译器必须执行JITed语言优化的完全优化。

如果你想要正确的话,有人会争辩你必须测量C ++编译时间= Java编译时间+第一次加载应用程序时JIT的时间,但我不认为这是正确和公平的,因为你正在将本地语言与JITed进行比较,或者将橙子与苹果进行比较。

答案 4 :(得分:2)

C ++编译器必须重复编译所有头文件,并且有很多头文件,所以这是减缓它的一件事。

答案 5 :(得分:2)

编译时更耗时的任务之一是代码优化。

Javac在进行编译时对代码进行了很少的优化。在运行应用程序时,JVM会完成优化。

编译时需要优化C / C ++,因为编译机器代码的优化很难。

答案 6 :(得分:2)

你的最后一句话是正确的:编译速度快的不是java或C#,由于语法和功能复杂,编译速度非常慢的C ++,最重要的是templates

答案 7 :(得分:2)

如果您认为javac快速尝试Jikes ....(请参阅http://jikes.sourceforge.net/)  它是一个用C ++编写的Java编译器。不幸的是,他们没有跟上最新的Java编译器规范,但如果你想快速看到它就是它。

答案 8 :(得分:1)

我认为部分原因是语言的复杂性。 C ++具有令人难以置信的可变性,能够覆盖几乎任何运算符或语法(如覆盖()运算符)。这意味着编译器必须执行 lot 更多的工作才能确定实际运行的操作,即使对于简单的事情也是如此。 Java和C#没有这个问题,因为语法是固定的,并且解析它们通常要简单得多。

答案 9 :(得分:1)

将像java这样的字节码语言与像C ++这样的本地编译语言进行比较有点困难。更好的比较是Delphi与C ++,其中Delphi的编译速度要快得多。由于这与优化或字节代码无关,因此必须归因于语言语法的差异以及包含与模块/单元的相对性能。

答案 10 :(得分:0)

Java编译器速度快吗?

Java到类的翻译应该是非常快速的,因为它只是一个带有一些语法检查的美化zip,所以如果与真正的编译器进行优化和目标代码生成相比,这是公平的#34;翻译&#34;从Java到班级是微不足道的。

与相当小的节目&#34; hello world&#34;做了比较。并且 - 和GCC(C / C ++ / Ada)相比,发现javac慢了30倍,而且在运行时变得更糟?