简体   繁体   English

在任何情况下,Java 都能比 C++ 更快吗?

[英]Can Java be faster C++ in any situation?

Is it possible for a Java application to be faster than a program written in C++? Java 应用程序是否可能比用 C++ 编写的程序更快? Also, what is release mode in compilation ?另外,编译中的发布模式是什么?

Unlike some people here, I'm going to be reasonable and answer the question that I know the OP intended to ask, even though his statement of it could have been better.与这里的某些人不同,我将理性地回答我知道 OP 打算提出的问题,即使他的陈述本可以更好。

Yes, a typical java implementation can be faster than a typical C++ implementation for real-world things.是的,对于现实世界的事物,典型的Java 实现可能典型的C++ 实现更快。 Even though Java has a few handicaps from being a safe, VM language, it makes up for some of them, too.尽管 Java 作为一种安全的 VM 语言存在一些缺陷,但它也弥补了其中的一些缺陷。

For one thing, since Java has a very abstract memory management scheme that does not allow raw pointers or untyped memory blocks to be manipulated, it can use a moving garbage collector.一方面,由于 Java 有一个非常抽象的内存管理方案,不允许操作原始指针或无类型内存块,因此它可以使用移动垃圾收集器。 In C++, untyped memory regions, unions, etc. would break this.在 C++ 中,无类型内存区域、联合等会破坏这一点。 Therefore, when a GC does not need to be run, allocations in Java can simply be a pointer bump.因此,当不需要运行 GC 时,Java 中的分配可能只是一个指针碰撞。 There is no practical way to do this in C++, since a fully moving GC cannot be implemented in a language that supports the kind of low level manipulations that C++ does.在 C++ 中没有实际的方法可以做到这一点,因为完全移动的 GC 不能在支持 C++ 所做的那种低级操作的语言中实现。

Furthermore, the VM of a typical implementation of Java is a double-edged sword relative to the statically compiled typical C++ implementation.此外,相对于静态编译的典型 C++ 实现,Java 的典型实现的 VM 是一把双刃剑。 The VM has some inherent overhead, but also allows some extra optimizations. VM 有一些固有的开销,但也允许一些额外的优化。 For example, let's say you have some kind of virtual function like (Please excuse incorrect syntax, as I don't regularly use Java):例如,假设您有某种虚拟函数,例如(请原谅不正确的语法,因为我不经常使用 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();

In C++, a virtual function call on foo.stuff() would likely have to be performed for all 1,000,000 iterations.在 C++ 中,可能必须在所有 1,000,000 次迭代中执行对 foo.stuff() 的虚函数调用。 In Java, the VM might be able to replace this with a direct call at runtime, after realizing that there is no semantically legal way for foo to be rebound to an object of class Foo2.在 Java 中,VM 可能能够在运行时用直接调用替换它,因为在意识到没有语义上合法的方式将 foo 重新绑定到类 Foo2 的对象之后。

Languages don't have a speed.语言没有速度。 A good Java compiler may generate more efficient code than a bad C++ compiler, and vice versa.一个好的 Java 编译器可能比一个坏的 C++ 编译器生成更高效的代码,反之亦然。 So which one is "fastest"?那么哪个是“最快”的呢?

Execution speed depends on several factors:执行速度取决于几个因素:

  • The compiler.编译器。 Different compilers generate different output code from the same input.不同的编译器从相同的输入生成不同的输出代码。
  • Your source code.你的源代码。 Some operations are cheap in one language, but expensive in others.有些操作在一种语言中很便宜,但在其他语言中很昂贵。 allocating memory with 'new' is far slower in C++ than in a managed language like C# or Java, for example)例如,在 C++ 中使用“new”分配内存比在 C# 或 Java 等托管语言中慢得多)
  • The system it's running on.它运行的系统。 (CPU's vary in how fast they can execute different code. What if your Java compiler turns out to generate code that runs really well on a Core 2, but my C++ compiler generates code that runs well on a Phenom? Which is fastest then? (CPU 执行不同代码的速度各不相同。如果你的 Java 编译器生成的代码在 Core 2 上运行得非常好,但我的 C++ 编译器生成的代码在 Phenom 上运行得很好?那么哪个最快?

But the language is in principle irrelevant.但语言原则上是无关紧要的。 Each language enforces certain guarantees which, might prevent certain optimizations.每种语言都强制执行某些保证,这可能会阻止某些优化。 But a clever compiler may determine that these guarantees can be safely bypassed in this particular case, making the optimization anyway.但是聪明的编译器可能会确定在这种特殊情况下可以安全地绕过这些保证,无论如何都会进行优化。 (For example, a Java compiler will often try to eliminate the bounds-checking that is required by the language). (例如,Java 编译器通常会尝试消除语言所需的边界检查)。 So it depends on the code you're testing (Java code ported to C++ will probably run better in the Java version, and vice versa), and on how you compile it and where you run it.因此,这取决于您正在测试的代码(移植到 C++ 的 Java 代码可能会在 Java 版本中运行得更好,反之亦然),以及您如何编译它以及在哪里运行它。

So as Martin York says, it's a silly question.所以正如 Martin York 所说,这是一个愚蠢的问题。 It's impossible to answer.无法回答。 Of course Java can be faster than C++ in some situations.当然,在某些情况下,Java 可能比 C++ 更快。 For example, if you write really good Java code and really bad C++ code.例如,如果您编写了非常好的 Java 代码和非常糟糕的 C++ 代码。 Or if you use a lousy C++ compiler.或者,如果您使用糟糕的 C++ 编译器。 Or if any of a million other things just so happen to favor the Java version a bit.或者,如果其他一百万件事情中的任何一件恰好偏向于 Java 版本。

Say after me: Languages don't have a speed .跟我说:语言没有速度

Which is fastest?哪个最快? English or french?英语还是法语? Both are just ways to associate meaning with sounds, or squiggles on paper.两者都只是将意义与声音或纸上的波浪线联系起来的方式。

The same applies to programming languages.这同样适用于编程语言。 A programming language is just a way to associate semantics with a sequence of characters in one or more files.编程语言只是将语义与一个或多个文件中的字符序列相关联的一种方式。

I think there are plenty of questions you can browse through that are similar.我认为您可以浏览很多类似的问题。 Have a look here, for example: C++ Performance vs. Java/C#看看这里,例如: C++ Performance vs. Java/C#

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

You can see c++ and java language comparison where few cases java is faster.您可以看到 c++ 和 java 语言比较,其中很少有 java 更快。 Also I have added a tables for Java and C++ and you ca see some other the cases are faster in java compared to C++.此外,我还为 Java 和 C++ 添加了一个表,您可以看到与 C++ 相比,Java 中的其他一些情况更快。

Lower numbers are better.数字越小越好。 Eg binary-trees search is better in java (2.89) secs versus 4.47 secs in c++.例如,二叉树搜索在 java (2.89) secs 中比在 c++ 中的 4.47 secs 更好。

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

Although most people wouldn't use them the same way it can be possible for a program written in Java to have similar speeds (in some cases even faster) than the same program written in C++.尽管大多数人不会以相同的方式使用它们,但用 Java 编写的程序可能具有与用 C++ 编写的相同程序相似的速度(在某些情况下甚至更快)。 (Let's assume for now, that both have the same algorithm implemented in the same way, neither of them uses some special trick that would not be available in the other language and this is not a special "benchmark" algorithm that builds on some special feature of a language/toolset) (让我们现在假设,两者都以相同的方式实现相同的算法,它们都没有使用其他语言中没有的特殊技巧,这不是建立在某些特殊功能上的特殊“基准”算法语言/工具集)

Or, at least that is what we have observed in our research: 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或者,至少这是我们在研究中观察到的: https : //www.researchgate.net/publication/352705416_Improving_productivity_in_large_scale_testing_at_the_compiler_level_by_changed_the_intermediate_language_from_C_to_Java

In this research project, we wanted to see if we could improve on the build performance (and so hopefully on developer productivity) by extending a compiler to use Java as an additional intermediate language, besides C/C++.在这个研究项目中,我们想看看我们是否可以通过扩展编译器以使用 Java 作为除 C/C++ 之外的附加中间语言来提高构建性能(并有望提高开发人员的生产力)。 This way could generate, from the same source code, programs written in C/C++ and Java, that built to executables that read the exact same configuration files, produced the exact same functional behavior, and generated the exact same logs.这种方式可以从相同的源代码生成用 C/C++ 和 Java 编写的程序,这些程序构建为读取完全相同的配置文件的可执行文件,产生完全相同的功能行为,并生成完全相同的日志。

We have observed that in this setup the binaries built via C/C++ started up faster.我们观察到,在此设置中,通过 C/C++ 构建的二进制文件启动速度更快。 The "binaries" built via Java became gradually faster, to the point where, in long-running scenarios, they could end up finishing earlier.通过 Java 构建的“二进制文件”变得越来越快,以至于在长时间运行的场景中,它们可能会提前完成。

Based on our measurement, most probably the Just In Time (JIT) compiler of the JVM was able to notice some optimization opportunities during execution, that were either missed by the C/C++ compiler used or only present themselves during execution.根据我们的测量,JVM 的即时 (JIT) 编译器很可能能够在执行期间注意到一些优化机会,这些机会要么被所使用的 C/C++ 编译器错过,要么仅在执行期间出现。 We hope to investigate this further in a follow-up research.我们希望在后续研究中对此进行进一步调查。

Most discussion compare applications compiled from source.大多数讨论比较从源代码编译的应用程序。 However if you have an old library eg from a third party, you can find that an old java library is much faster as it will still be able to use the latest instructions/techniques whereas an old library already compiled to native code cannot.但是,如果您有一个旧的库,例如来自第三方的库,您会发现旧的 java 库要快得多,因为它仍然能够使用最新的指令/技术,而已经编译为本机代码的旧库则不能。

I guess the most interesting thing you can say on this topic is that a modern JVM does some speculative optimizations.我想关于这个话题你能说的最有趣的事情是现代 JVM 做了一些推测性优化。 Optimizations based on guesses about the stableness of some values, whith the possibility to unoptimize that code if the value should change in the future.基于对某些值稳定性的猜测进行优化,如果将来该值发生变化,则有可能取消优化该代码。

OTOH this is nothing inherent with the languages in question. OTOH 这不是所讨论的语言所固有的。 I saw a research project a couple of years ago that managed to get an extra 20% out of some natively compiled code (maybe even from C++) by running it in an emulator emulating the same CPU as the hardware but performing some VM-style optimizations on the code.几年前我看到一个研究项目,通过在仿真与硬件相同的 CPU 但执行一些 VM 风格的优化的模拟器中运行它,设法从一些本机编译的代码(甚至可能来自 C++)中获得额外的 20%在代码上。

If I believe what some Java evangelist say, I would answer "yes" to the first question.如果我相信某些 Java 传道者所说的话,我会对第一个问题回答“是”。 Ie. IE。 a Java program "can" be faster. Java 程序“可以”更快。 Not always, though...但并非总是如此...
These Java evangelists point out the better memory management, avoiding overhead of new , etc.这些 Java 布道者指出了更好的内存管理,避免了new等的开销。

To answer the second question, release mode for a C/C++ compiler means a compilation without debugging information: the latter stores additional information like line numbers corresponding to generated code (easier for debugging and error reporting), and avoids optimizations (which can change code order and mess with above info).回答第二个问题,C/C++编译器的发布模式意味着没有调试信息的编译:后者存储额外的信息,如生成代码对应的行号(更容易调试和错误报告),并避免优化(可以更改代码订购并弄乱上述信息)。
So release mode is, in general, faster and smaller.因此,发布模式通常更快、更小。 And can crash where the debug mode works!并且可以在调试模式工作的地方崩溃! (Rare but I saw that.) (很少见,但我看到了。)

Release Mode means that you build your program because you want to release it out to the public.发布模式意味着您构建程序是因为您想将其发布给公众。 Usually, the compiler will try harder to make the executable smaller and faster.通常,编译器会更加努力地使可执行文件更小更快。 This often means getting rid of symbol information needed get a backtrace of a crash and using a higher optimize level.这通常意味着摆脱所需的符号信息以获得崩溃的回溯并使用更高的优化级别。 The latter makes compilation time slower, so it's not used when building in Debug Mode .后者使编译时间变慢,因此在Debug Mode 下构建时不使用它。

Yes it can .是的,它可以 The JIT compiler can optmize the code to run faster. JIT 编译器可以优化代码以更快地运行。 While in C++ you have to do that optmization by hand.在 C++ 中,您必须手动进行优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM