Java在任何情况下都可以更快地使用C ++吗?

时间:2009-01-01 22:55:54

标签: java c++ performance

Java应用程序是否可能比用C ++编写的程序更快?另外,编译中的发布模式是什么?

11 个答案:

答案 0 :(得分:19)

与这里的某些人不同,我会合情合理地回答我知道OP打算提出的问题,即使他的陈述可能会更好。

是的,典型的 java实现可以典型的 C ++实现更快真实世界的东西。尽管Java在安全的虚拟机语言方面有一些障碍,但它也弥补了其中的一部分。

首先,由于Java有一个非常抽象的内存管理方案,它不允许操作原始指针或无类型内存块,因此它可以使用移动垃圾收集器。在C ++中,无类型的内存区域,联合等会破坏这一点。因此,当不需要运行GC时,Java中的分配可能只是一个指针凹凸。在C ++中没有实用的方法,因为完全移动的GC不能用支持C ++所做的低级操作的语言来实现。

此外,相对于静态编译的典型C ++实现,典型Java实现的VM是一把双刃剑。 VM具有一些固有的开销,但也允许一些额外的优化。例如,假设您有某种虚函数(请原谅不正确的语法,因为我不经常使用Java):

abstract class Foo {
    void stuff() {}
}

class Foo1 extends Foo {
    void stuff()  {
        System.out.println("Foo1");
    }
}

class Foo2 extends Foo {
    void stuff()  {
        System.out.println("Foo2");
    }
}

// Somewhere in program initialization:
Foo foo;
if(args[0] == "Foo1")
    foo = new Foo1();
 else foo = new Foo2;
 for(int i = 0; i < 1000000; i++)
     foo.stuff();

在C ++中,可能必须对所有1,000,000次迭代执行foo.stuff()上的虚函数调用。在Java中,VM可能能够在运行时通过直接调用替换它,因为我们意识到foo没有语法合法的方式可以反弹到类Foo2的对象。

答案 1 :(得分:13)

语言没有速度。一个好的Java编译器可能会生成比错误的C ++编译器更高效的代码,反之亦然。哪一个“最快”?

执行速度取决于几个因素:

  • 编译器。不同的编译器从同一输入生成不同的输出代码。
  • 您的源代码。有些操作在一种语言中便宜,但在其他语言中则很昂贵。使用'new'分配内存在C ++中比在C#或Java之类的托管语言中慢得多,例如)
  • 正在运行的系统。 (CPU在执行不同代码的速度方面有所不同。如果你的Java编译器生成的代码在Core 2上运行得非常好,但我的C ++编译器生成的代码在Phenom上运行良好怎么办?那么哪个最快? / LI>

但语言原则上无关紧要。每种语言都强制执行某些保证,可能阻止某些优化。但是,聪明的编译器可能会确定在这种特定情况下可以安全地绕过这些保证,无论如何都要进行优化。 (例如,Java编译器通常会尝试消除语言所需的边界检查)。因此,它取决于您正在测试的代码(移植到C ++的Java代码可能在Java版本中运行得更好,反之亦然),以及编译它的方式以及运行它的位置。

正如马丁约克所说,这是一个愚蠢的问题。这是不可能回答的。 当然在某些情况下,Java可能比C ++更快。例如,如果您编写非常好的Java代码和非常糟糕的C ++代码。或者如果您使用糟糕的C ++编译器。或者,如果其他任何一百件事情都恰好支持Java版本。

跟我说:语言没有速度

哪个最快?英语还是法语?两者都只是将意义与声音联系在一起的方式,或者是纸上的曲折。

这同样适用于编程语言。编程语言只是将语义与一个或多个文件中的字符序列相关联的一种方式。

答案 2 :(得分:7)

我认为你可以通过类似的问题浏览很多问题。看看这里,例如:C++ Performance vs. Java/C#

答案 3 :(得分:2)

是的,它可以:制作一个使用好算法的Java程序,以及一个使用坏算法的C ++程序,Java版本可能会更快。

答案 4 :(得分:1)

你可以看到c ++和java语言comparison,其中java的速度很快。 此外,我还为Java和C ++添加了一个表,您可以看到其他一些案例在Java中比C ++更快。

数字越少越好。例如,二进制树搜索在java(2.89)秒中比在c ++中4.47秒更好。

http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=javaxx&lang2=javaxx

 Java 6 -Xms64m measurements
Program & Logs  Time secs   Memory KB   Size B   N 
binary-trees    2.89    39,436  603  16
chameneos-redux 17.01   17,316  1429     6,000,000
fannkuch    11.08   8,996   555  11
fasta   21.40   9,300   1240     25,000,000
k-nucleotide    15.57   83,308  1052     1,000,000
mandelbrot  3.25    11,136  665  3,000
meteor-contest  0.80    14,196  5177     2,098
n-body  14.84   11,652  1424     20,000,000
nsieve  2.22    15,748  296  9
nsieve-bits 5.04    13,468  523  11
partial-sums    9.14    8,600   474  2,500,000
pidigits    1.92    9,112   938  2,500
recursive   6.82    12,180  427  11
regex-dna   7.60    75,192  921  500,000
reverse-complement  1.13    61,124  592  2,500,000
spectral-norm   24.00   12,268  514  5,500
startup 17.23       112  200
sum-file    4.11    10,084  226  21,000
thread-ring 134.99  27,628  530  10,000,000

http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=gpp&lang2=gpp

 C++ GNU g++ measurements
Program & Logs  Time secs   Memory KB   Size B   N 
binary-trees    4.47    6,996   541  16
chameneos-redux 16.69   1,004   1729     6,000,000
fannkuch    7.78    844 554  11
fasta   18.72   788 1248     25,000,000
k-nucleotide    7.46    9,304   1380     1,000,000
mandelbrot  3.02    896 1097     3,000
meteor-contest  0.15    792 5311     2,098
n-body  14.62   932 1705     20,000,000
nsieve  2.08    5,764   313  9
nsieve-bits 3.86    3,316   494  11
partial-sums    4.05    852 531  2,500,000
pidigits    1.66    1,052   652  2,500
recursive   2.40    1,008   566  11
regex-dna   5.58    12,704  1588     500,000
reverse-complement  0.54    13,288  810  2,500,000
spectral-norm   23.84   900 442  5,500
startup 0.86        108  200
sum-file    6.47    852 260  21,000
thread-ring 101.28  2,960   626  10,000,000

答案 5 :(得分:1)

尽管大多数人不会以相同的方式使用它们,但用 Java 编写的程序可能具有与用 C++ 编写的相同程序相似的速度(在某些情况下甚至更快)。 (让我们暂时假设,两者都以相同的方式实现相同的算法,它们都没有使用其他语言中没有的特殊技巧,这不是建立在某些特殊功能上的特殊“基准”算法语言/工具集)

或者,至少这是我们在研究中观察到的:https://www.researchgate.net/publication/352705416_Improving_productivity_in_large_scale_testing_at_the_compiler_level_by_changing_the_intermediate_language_from_C_to_Java

在这个研究项目中,我们想看看我们是否可以通过扩展编译器以使用 Java 作为 C/C++ 之外的附加中间语言来提高构建性能(并希望因此提高开发人员的工作效率)。 这种方式可以从相同的源代码生成用 C/C++ 和 Java 编写的程序,这些程序构建为读取完全相同的配置文件、产生完全相同的功能行为并生成完全相同的日志的可执行文件。

我们观察到,在此设置中,通过 C/C++ 构建的二进制文件启动速度更快。通过 Java 构建的“二进制文件”变得越来越快,以至于在长时间运行的场景中,它们可能会提前完成。

根据我们的测量,JVM 的即时 (JIT) 编译器很可能能够在执行期间注意到一些优化机会,这些机会要么被所使用的 C/C++ 编译器错过,要么仅在执行期间出现。我们希望在后续研究中对此进行进一步调查。

答案 6 :(得分:0)

如果我相信一些Java传道者所说的话,我会对第一个问题回答“是”。 IE浏览器。 Java程序“可以”更快。但并非总是如此...... 这些Java传播者指出了更好的内存管理,避免了new等的开销。

要回答第二个问题,C / C ++编译器的发布模式意味着没有调试信息的编译:后者存储其他信息,如与生成的代码对应的行号(更容易进行调试和错误报告),并避免优化(可以改变代码顺序和上面的信息混乱) 因此,释放模式通常更快更小。并且可以在调试模式工作的地方崩溃! (很少见,但我看到了。)

答案 7 :(得分:0)

发布模式意味着您构建程序是因为您希望将其发布给公众。通常,编译器会更加努力地使可执行文件更小更快。这通常意味着摆脱所需的符号信息,获得崩溃的回溯并使用更高的优化级别。后者使编译时间变慢,因此在调试模式中构建时不会使用它。

答案 8 :(得分:0)

大多数讨论比较从源代码编译的应用程序。但是,如果您有一个旧库,例如从第三方开始,您可以发现旧的Java库要快得多,因为它仍然能够使用最新的指令/技术,而已经编译为本机代码的旧库则不能。

答案 9 :(得分:0)

我想你可以在这个主题上说的最有趣的事情是现代JVM做了一些推测性的优化。优化基于对某些值的稳定性的猜测,如果值在将来发生变化,则可能无法优化该代码。

OTOH这不是所讨论的语言所固有的。几年前我看到一个研究项目,通过在模拟器中运行它来模拟与硬件相同的CPU但是执行一些VM样式的优化,设法从一些本机编译的代码(甚至可能来自C ++)中获得额外的20%关于代码。

答案 10 :(得分:-3)

是的可以。 JIT编译器可以优化代码以更快地运行。在C ++中,您必须手动进行优化。