Java 运行时性能与本机 C/C++ 代码的比较?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1984856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Runtime Performance Vs Native C / C++ Code?
提问by D.C.
I've become more and more comfortable programming in Java than with C++ or C. I am hoping to get a sense of the performance hit incurred using a JVM interpreter, as opposed to executing the same "project" natively. I realize that there is some level of subjectivity here; the quality of the program will depend highly on a good implementation. I'm interested in the following aspects in a general sense:
与使用 C++ 或 C 相比,我越来越习惯使用 Java 编程。我希望了解使用 JVM 解释器所带来的性能损失,而不是本机执行相同的“项目”。我意识到这里有一定程度的主观性;方案的质量将在很大程度上取决于良好的实施。我对一般意义上的以下几个方面感兴趣:
There must be some baseline for overhead when using an interpreter. Is there some general rule of thumb to remember? 10% 15%? (I pulled these numbers out of thin air) I have read the occasional blog stating that Java code is nearly as fast as native code, but I think that may have been biased.
Does the JVM garbage collector add significant overhead to runtime performance? I know Cocoa applications have begun to use a garbage collection model, and i agree that it makes programming a lot simpler, but at what cost?
What is the overhead of making system calls from Java? For example creating a Socket object as opposed to the C socket API.
Finally, I recall reading somewhere that the JVM implementation is single threaded. If this is true (which i am skeptical about), does that mean that Java threads really aren't true threads? Does a java thread, in general, correspond to an underlying kernel-provided thread? Does a Java application benefit in the same way a native application would from multiple cores / multiple cpu's?
使用解释器时必须有一些开销基线。是否有一些一般的经验法则要记住?10% 15%?(我凭空得出这些数字)我偶尔读过一篇博客,其中提到 Java 代码几乎与本机代码一样快,但我认为这可能有偏见。
JVM 垃圾收集器是否会显着增加运行时性能的开销?我知道 Cocoa 应用程序已经开始使用垃圾收集模型,我同意它使编程变得更简单,但代价是什么?
从 Java 进行系统调用的开销是多少?例如,创建一个 Socket 对象而不是 C 套接字 API。
最后,我记得在某处读到 JVM 实现是单线程的。如果这是真的(我对此表示怀疑),那是否意味着 Java 线程真的不是真正的线程?java 线程通常是否对应于底层内核提供的线程?Java 应用程序是否与本机应用程序从多个内核/多个 CPU 中受益的方式相同?
Any advice from developer who understands the intricacies of JVM and java program performance would be much appreciated. Thanks.
非常感谢了解 JVM 和 Java 程序性能复杂性的开发人员的任何建议。谢谢。
采纳答案by jalf
Java isn't an interpreted language, and hasn't been for several versions. The Java bytecode is JIT'ed on the fly. (Technically it still interprets some of the code, but anything that matters performance-wise gets JIT'ed)
Java 不是一种解释型语言,并且还没有出现过多个版本。Java 字节码是即时 JIT 的。(从技术上讲,它仍然会解释一些代码,但任何与性能有关的东西都会被 JIT 处理)
As for performance, what on Earth gives you the crazy idea that "there is a baseline for overhead"? There isn't. There never was and never will be. Not betwee C++ and Java, and not between Python and Javascript, or anyother two languages. There are things that your specific version of the JVM will do faster than your specific C++ compiler, and things that your specific C++ compiler will do better than your specific JVM.
至于性能,究竟是什么让您产生了“开销有一个基线”的疯狂想法?没有。从来没有,也永远不会有。不在 C++ 和 Java 之间,也不在 Python 和 Javascript 或任何其他两种语言之间。有些事情您的特定 JVM 版本会比您的特定 C++ 编译器做得更快,而您的特定 C++ 编译器会比您的特定 JVM 做得更好。
So the "overhead" of your choice of language depends entirely on 1) what you want your code to do, and 2) how you write your code.
因此,您选择语言的“开销”完全取决于 1)您希望代码做什么,以及 2)您如何编写代码。
If you take a Java program and translate it to C++, the result will almost certainly run slower.
如果您将 Java 程序转换为 C++,结果几乎肯定会运行得更慢。
If you take a C++ program and translate it to Java, that too will also run slower.
如果你把一个 C++ 程序翻译成 Java,它也会运行得更慢。
Not because one language is "faster" than the other, but because the original program was written for one language, and was tailored to work well in thatlanguage. And any attempt to translate it to another language will lose this advantage. You end up with a C++-style Java program, which won't run efficiently on the JVM, or a Java-style C++ program, which will run terriblyas well.
不是因为一种语言比另一种语言“更快”,而是因为原始程序是为一种语言编写的,并且是为在该语言中很好地工作而量身定制的。任何将其翻译成另一种语言的尝试都将失去这一优势。您最终会得到一个 C++ 风格的 Java 程序,它不会在 JVM 上高效运行,或者一个 Java 风格的 C++ 程序,它也会运行得非常糟糕。
Neither language specification contains a clause that "and the result must be at least x% slower than language y". Both your C++ compiler and the JVM do their very best to make things go fast.
两种语言规范都没有包含“并且结果必须至少比语言 y 慢 x%”的子句。您的 C++ 编译器和 JVM 都尽最大努力使事情进展得更快。
And then performance characteristics you're seeing today may change tomorrow. Languages don't have a speed.
然后你今天看到的性能特征明天可能会改变。语言没有速度。
But to answer your specific questions:
但要回答您的具体问题:
There must be some baseline for overhead when using an interpreter. Is there some general rule of thumb to remember? 10% 15%? I have read the occasional blog stating that Java code is nearly as fast as native code, but I that may have been biased.
使用解释器时必须有一些开销基线。是否有一些一般的经验法则要记住?10% 15%?我偶尔读过一篇博客,说 Java 代码几乎和本机代码一样快,但我可能有偏见。
As said above, it depends. For many common tasks, you typically won't see more than a few percents difference either way. For some use cases, you'll see a larger difference (going either way. Both languages have advantages when it comes to performance. There is some overhead associated with the JVM, but there are also huge optimization opportunities and not least the garbage collector)
如上所述,这取决于。对于许多常见任务,无论哪种方式,您通常都不会看到超过百分之几的差异。对于某些用例,您会看到更大的差异(无论哪种方式。两种语言在性能方面都有优势。有一些与 JVM 相关的开销,但也有巨大的优化机会,尤其是垃圾收集器)
Does the JVM garbage collector add significant overhead to runtime performance? I know Cocoa applications have begun to use a garbage collection model, and i agree that it makes programming a lot simpler, but at what cost?
JVM 垃圾收集器是否会显着增加运行时性能的开销?我知道 Cocoa 应用程序已经开始使用垃圾收集模型,我同意它使编程变得更简单,但代价是什么?
Basically none. On average, a garbage collector is far fasterthan manual memory management, for many reasons:
基本没有。平均而言,垃圾收集器比手动内存管理快得多,原因有很多:
- on a managed heap, dynamic allocations can be done much faster
- shared ownership can be handled with negligible amortized cost, where in a native language you'd have to use reference counting which is awfully expensive
- in some cases, object destruction is vastly simplified as well (Most Java objects can be reclaimed just by GC'ing the memory block. In C++ destructors must alwaysbe executed, and nearly every object has one)
- 在托管堆上,动态分配可以更快地完成
- 共享所有权可以以微不足道的摊销成本处理,在本地语言中,您必须使用非常昂贵的引用计数
- 在某些情况下,对象销毁也大大简化(大多数 Java 对象可以通过对内存块进行 GC 回收。在 C++ 中必须始终执行析构函数,并且几乎每个对象都有一个)
The main problem with a GC is that while on average a garbage collector performs better, you lose some control over whento take the performance cost. Manual memory management ensures your thread won't ever be halted while waiting for memory to be cleaned up. A garbage collector can, at almost any time, decide to pause the process and clean up memory. In almost all cases, this is fast enough to be no problem, but for vital real-time stuff, it is a problem.
GC 的主要问题是,虽然平均而言垃圾收集器性能更好,但您无法控制何时采取性能成本。手动内存管理可确保您的线程在等待内存清理时永远不会停止。垃圾收集器几乎可以随时决定暂停进程并清理内存。在几乎所有情况下,这都足够快,没有问题,但对于重要的实时内容,这是一个问题。
(An additional problem is that you lose a bit of expressiveness. In C++, RAII is used to manage all sorts of resources. In Java, you can't use RAII. Instead the GC handles memory for you, and for all other resources, you're screwed, and have to do it yourself with lots of try/finally blocks. There is no reason why RAII couldn't be implemented in a GC'ed language, but it's not available in either Java or C#)
(另一个问题是你失去了一点表达能力。在 C++ 中,RAII 用于管理各种资源。在 Java 中,你不能使用 RAII。相反,GC 为你和所有其他资源处理内存,你被搞砸了,必须自己用很多 try/finally 块来完成。没有理由不能用 GC 语言实现 RAII,但它在 Java 或 C# 中都不可用)
What is the overhead of making system calls from Java? For example creating a Socket object as opposed to the C socket API.
从 Java 进行系统调用的开销是多少?例如,创建一个 Socket 对象而不是 C 套接字 API。
Roughly the same. Why would it be different? Of course, Java has to invoke the relevant OS services and APIs, so there is a tiny bit of overhead, but it is really nothing you're likely to notice.
大致相同。为什么会不一样?当然,Java 必须调用相关的 OS 服务和 API,因此有一点点开销,但实际上您可能不会注意到。
Finally, I recall reading somewhere that the JVM implementation is single threaded. If this is true (which i am skeptical about), does that mean that Java threads really aren't true threads? Does a java thread, in general, correspond to an underlying kernel-provided thread? Does a Java application benefit in the same way a native application would from multiple cores / multiple cpu's?
最后,我记得在某处读到 JVM 实现是单线程的。如果这是真的(我对此表示怀疑),那是否意味着 Java 线程真的不是真正的线程?java 线程通常是否对应于底层内核提供的线程?Java 应用程序是否与本机应用程序从多个内核/多个 CPU 中受益的方式相同?
Java can use multiple threads, yes. The JVM itselfmight be singlethreaded (in the sense that all the JVM services run on the same thread), I don't know about that. But your Java applicationcan use as many threads as it likes, and they are mapped to OS threads and will use multiple cores.
Java 可以使用多个线程,是的。JVM本身可能是单线程的(所有 JVM 服务都运行在同一个线程上),我对此一无所知。但是您的 Java应用程序可以使用任意数量的线程,并且它们被映射到操作系统线程并且将使用多个内核。
回答by Bozho
http://www.w3sys.com/pages.meta/benchmarks.html
http://www.w3sys.com/pages.meta/benchmarks.html
http://www.freewebs.com/godaves/javabench_revisited/
http://www.freewebs.com/godaves/javabench_revisited/
http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B#Performance
http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B#Performance
http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/
http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/
http://www.irrlicht3d.org/pivot/entry.php?id=446
http://www.irrlicht3d.org/pivot/entry.php?id=446
And so on. The fact is - it doesn't matter. Bottlenecks and slow software are created by the developers, not by the language (at least nowadays).
等等。事实是——没关系。瓶颈和缓慢的软件是由开发人员创建的,而不是由语言创建的(至少现在是这样)。
回答by jqno
Actually, a VM can do a lot of optimizations at runtime, based on information that's only available at runtime, that a C/C++ compiler cannot do. So, in most circumstances, the JVM will be at least as fast as a native program.
实际上,基于仅在运行时可用的信息,VM 可以在运行时进行大量优化,而 C/C++ 编译器无法做到这一点。因此,在大多数情况下,JVM 将至少与本机程序一样快。
Brian Goetz answers most, if not all of your questions in his talk Towards a universal VM.
Brian Goetz 在他的演讲Towards a Universal VM 中回答了你的大部分问题,如果不是全部的话。
回答by Stephan Eggermont
Both java and c# (and objective-c) are not nearly as fast as native code can be. But that only matters if you have a problem where you are not engineering-time limited. Because you'll have the time to devise a better algorithm with a high level language.
java和c#(和objective-c)都没有本地代码那么快。但这仅在您遇到不受工程时间限制的问题时才重要。因为您将有时间使用高级语言设计更好的算法。
So basically, if you're developing a device where you're going to build a million a year of, or that is battery powered, you don't use java or c# to build its core functionality. You might add a lisp interpreter to make customisation easy, though. Microsoft is not going to use c# for say the core of SQL server, where performance really matters. Visual Studio on the other hand, where MS can expect users to have high-end hardware, can be used as a showcase for slow but high productivity technology.
所以基本上,如果你正在开发一个设备,你打算每年生产一百万,或者是电池供电,你不会使用 java 或 c# 来构建其核心功能。不过,您可以添加一个 lisp 解释器来简化定制。Microsoft 不会将 C# 用于 SQL Server 的核心,因为性能确实很重要。另一方面,MS 可以期望用户拥有高端硬件的 Visual Studio 可以用作缓慢但高生产力技术的展示。
Please note that I currently do most of my programming in Pharo Smalltalk, which is a lot slower than java, c# or objective-c, and is not even one of the fastest Smalltalks. Productivity trumps performance.
请注意,我目前的大部分编程都是在 Pharo Smalltalk 中完成的,它比 java、c# 或 Objective-c 慢很多,甚至不是最快的 Smalltalks 之一。生产力胜过绩效。
回答by JesperE
To address each of your points:
要解决您的每一点:
- The overhead of interpretingcode is much higher than 10-15% (I'd guess at along 3x-5x or higher). In order to get down to 10-15% you have to use some form of machine-code compilation step (i.e. JIT). (Try running a JVM with JIT switched off, and you'll see the performance drop like a rock.)
- Garbage collection does have a performance impact, but I'd say that everyone agrees that it is worth it. If you can afford the byte-code compilation/interpretation overhead, you can afford the gc overhead as well.
- Socket programming is much easier in Java than in C/C++, if that's what you're asking. And performancewise, the socket I/O overhead dominates over the Java execution overhead.
- Most modern JVMs have true threads, i.e. each Java thread is executed by a kernel thread, allowing Java threads to utilize modern multi-core CPUs.
- 解释代码的开销远高于 10-15%(我猜是 3x-5x 或更高)。为了降低到 10-15%,您必须使用某种形式的机器代码编译步骤(即 JIT)。(尝试在关闭 JIT 的情况下运行 JVM,您会看到性能像石头一样下降。)
- 垃圾收集确实对性能有影响,但我想说每个人都同意这是值得的。如果你能负担得起字节码编译/解释的开销,你也能负担得起 gc 的开销。
- 如果您要问的是,Java 中的套接字编程比 C/C++ 中的要容易得多。在性能方面,套接字 I/O 开销高于 Java 执行开销。
- 大多数现代 JVM 都有真正的线程,即每个 Java 线程由一个内核线程执行,允许 Java 线程利用现代多核 CPU。
回答by TofuBeer
There isn't an easy answer to this. Writing C style C++ is possible (even a good idea) but once you try to do inheritance in C, things get ugly. So ignore C and go with Java -vs- C++since they are closer to one another.
对此没有简单的答案。编写 C 风格的 C++ 是可能的(甚至是一个好主意)但是一旦你尝试在 C 中进行继承,事情就会变得丑陋。所以忽略 C 并使用Java -vs- C++,因为它们彼此更接近。
To get a real sense of it you would need to write two relatively large applications in similar manner in both languages. If you do that then do you use the STL and the Java collection classes or do you write your own and port them between languages? If you use the native one then it depends on which implementation is faster where as if you use your own you are not testing the real speed of the application.
要真正了解它,您需要用两种语言以类似的方式编写两个相对较大的应用程序。如果您这样做,那么您是使用 STL 和 Java 集合类还是自己编写并在语言之间移植它们?如果您使用本机,则取决于哪种实现更快,而如果您使用自己的实现,则不会测试应用程序的实际速度。
I'd say you would need to write the application as similar as possible but use the language specific libraries/idioms where it makes sense. C++ and Java code, while being similar, have different ways of doing things - something that is easy in Java may be terribly hard in C++ and vice versa.
我会说你需要编写尽可能相似的应用程序,但在有意义的地方使用特定于语言的库/习语。C++ 和 Java 代码虽然相似,但有不同的做事方式 - 在 Java 中容易的事情在 C++ 中可能非常困难,反之亦然。
A modern GC implementation doesn't add that much overhead, and you can switch to a GC in C++to do the comparison if you like :-)
现代 GC 实现不会增加那么多开销,如果您愿意,可以切换到C++ 中的GC 进行比较:-)
There are some things that the Java runtime can do that is not generally done in C++ compilers, such as the ability to inline virtual methods.
Java 运行时可以做一些通常在 C++ 编译器中无法完成的事情,例如内联虚拟方法的能力。
For system type things Java typically resorts to making calls into C so there is overhead there (though JNI is faster than it used to be).
对于系统类型的东西,Java 通常求助于调用 C,所以那里有开销(尽管 JNI 比以前快)。
Threading depends on the implementation. Sun used to use "green threads; for Solaris, but that is long gone. As far as I know most (all?) modern VMs use native Threads.
线程取决于实现。Sun 曾经使用“绿色线程;对于 Solaris,但那早已不复存在。据我所知,大多数(所有?)现代 VM 都使用本机线程。
In short I don't think there is a good metric on the % overhead for Java -vs- C++, and any that you find are likely to be micro benchmarks that do not represent the real world (unfortunately).
简而言之,我认为 Java -vs- C++ 的开销百分比没有很好的衡量标准,您发现的任何指标都可能是不代表现实世界的微基准测试(不幸的是)。
回答by exabytes18
A lot of people underestimate the performance of java. I was once curious about this as well and wrote a simple program in java and then an equivalent in c (not much more than doing some operation with a for loop and a massive array). I don't recall exact figures, but I do know that java beat out c when the c program was not compiled with any optimization flags (under gcc). As expected, c pulled ahead when I finally compiled it with aggressive optimization. To be honest, it wasn't a scientific experiment by any means, but it did give me a baseline of knowing just where java stood.
很多人低估了java的性能。我曾经对此也很好奇,并用 java 编写了一个简单的程序,然后用 c 编写了一个等价的程序(只不过是用 for 循环和大量数组进行一些操作)。我不记得确切的数字,但我知道当 c 程序没有使用任何优化标志(在 gcc 下)编译时,java 击败了 c。正如预期的那样,当我最终通过积极的优化编译它时,c 领先了。老实说,这绝不是一个科学实验,但它确实让我知道 java 的位置。
Of course, java probably falls further behind when you start doing things that require system calls. Though, I have seen 100MB/s read performance with disks and network with java programs running on modest hardware. Not sure what that says exactly, but it does indicate to me that it's good enough for pretty much anything I'll need it for.
当然,当你开始做需要系统调用的事情时,java 可能会更落后。尽管如此,我已经看到使用在普通硬件上运行的 Java 程序的磁盘和网络的读取性能达到 100MB/s。不确定这到底是什么意思,但它确实向我表明它足以满足我需要的几乎任何事情。
As for threads, if your java program creates 2 threads, then you have 2 realthreads.
至于线程,如果你的java程序创建了2个线程,那么你就有2个真正的线程。
回答by Xinus
Important thing to note down is
需要注意的重要一点是
Java byte code JIT compiled to much more optimized code specific to particular hardware
Java 字节码 JIT 编译为特定于特定硬件的更优化的代码
vs
对比
C code compiled and optimized to general hardware so it cannot take advantage of features provided by specific hardware
C 代码针对通用硬件进行编译和优化,因此无法利用特定硬件提供的功能
回答by igouy
As your objective is very modest "I am hoping to get a sense of the performance hit..."you should be able to fulfill most of it by examining the programs and measurements shown in the Computer Language Benchmarks Game.
由于您的目标非常有限,“我希望了解性能受到的影响……”您应该能够通过检查计算机语言基准游戏中显示的程序和测量来实现大部分目标。
As you know both Java and C++
正如您所知道的 Java 和 C++
you can look at the program source code and decide for yourself which of the Java programsare reasonable to compare with which of the C and C++ programs
you can look at the dozen different tasksand decide for yourself which of them exercise your idea of "the most basic features of each language"
you can look at the different approaches to multicore, or programs forced onto one core
you can check how much JVM startup might or might not effect those measurements
您可以查看程序源代码并自己决定哪些Java 程序可以与哪些 C 和C++ 程序进行比较
您可以查看实现多核的不同方法,或强制使用一个核的程序
您可以检查有多少 JVM 启动可能会或可能不会影响这些测量
But you do have to thinkabout whether measurements of tiny programs can plausibly indicate the likely performance of yourapplication.
但是您必须考虑对小程序的测量是否可以合理地表明您的应用程序可能的性能。