views:

1741

answers:

13

Java was initially slow before the JIT but today performance is pretty close to C++. I want to know if someone has done measurable performance comparisons between the two languages? Where does Java fall short when compared to C++? Java provides many productivity gains to developers so they can write applications much quicker because of garbage college, lack of pointers, etc. Applications such as Firefox, Webkit and Open Office, for example, could be developed much more quickly and reliably if written in 100% Java, perhaps by a factor of 2, but developers still choose C/C++ for performance reasons. Can someone demonstrate where Java cannot be made to perform as well as C++ for applications like the ones that I mentioned.

Let me just add that much application work is still being done in C++ for a reason. This is meant to be more than a subjective questions. Languages with higher levels of abstraction frequently pay a performance penalty. We would all be programming in higher level languages if this penalty did not exist. Where does still Java pay in comparison to C++? Be specific.

+6  A: 

In many ways this is like comparing apples to oranges.

C++ is built on the notion that you don't pay a cost for anything you don't use. If you manage memory yourself, if you don't use virtual functions, etc.

Java doesn't give you that freedom. It gives you features that you may not even want. For all you may want to allocate memory yourself, you will have to use heap objects for everything, so you will take a garbage collection impact.

Once you start talking about GUIs, it's an even more difficult comparison since different UI frameworks and toolkits have different performance issues. For example, Swing/AWT will typically be slower than something written directly for the native OS. In C++, you will rarely find a truly portable toolkit, etc.

I think that when developers started openoffice, Java was much slower and the UI toolkits were slow and ugly. Tools like Eclipse prove that you can build relatively nice UIs even in Java, though admittedly, SWT is a toolkit that does a lot of things at the native level.

Uri
You can allocate memory yourself - just allocate a nice large byte array and hand out indexes into it. It won't be pleasant (you won't have types), but you can write your own suballocator if you really, really must.
Barry Kelly
If you don't have types that's hardly giving you the ability to manage memory yourself is it
1800 INFORMATION
Barry, I meant allocate objects... Not sure what you can really do with just a good old array...
Uri
+4  A: 

I don't believe anyone can prove that C++ will always be meaningfully faster than Java for the simple fact that you can always revert to JNI to get native speed from Java.

See, for example, SWT which are the graphical tools built by IBM (I think) meant to replace Swing and give both native performance and look-and-feel.

I, for one, would prefer the ease of development over speed since I consider minimal development time to be more important than raw application speed, especially when I can still get that speed - I can have both the ease-of-development of Java with speed of compiled languages.

paxdiablo
C++ will always be faster than C++?
Eran Galperin
Good catch, fixed now, but at least you couldn't fault the truthfulness of the statement :-)
paxdiablo
Because as soon as you read it, its performance increased by one? :)
Uri
+10  A: 

To complete Pax's and Uri's answer, here are some recent benchmarks:

As said, those are two very different languages, and some are convinced that Java will ever be slower than C++ because of:

  • Heap allocation for all objects (even small ones like iterators)
  • lots of dynamic castings
  • increased memory usage

[Humor]

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." Mr. Bunny

As mentioned by dribeas in the comments, Heap allocation is not a good argument.
This "Urban performance legends, revisited" mentions:

"Garbage collection will never be as efficient as direct memory management." And, in a way, those statements are right -- dynamic memory management is not as fast -- it's often considerably faster.
The malloc/free approach deals with blocks of memory one at a time, whereas the garbage collection approach tends to deal with memory management in large batches, yielding more opportunities for optimization (at the cost of some loss in predictability).

VonC
+1 on being familiar with Mr. Bunny.
Uri
- Memory allocation in Java is almost free (about 10 machine instructions), and only alive objects incur cost for the GC, so the first point is false.
David Rodríguez - dribeas
People should not argue about things they dont know. Heap allocation, dynamic casting... Very documented and very objective answer. That is ironic.
Gilles
dribeas: It's not quite that simple. 10 instructions, and then what? All your objects have magically been GC'ed? How about the overhead required to make GC possible? Objects have to store more data, making them more expensive to initialize, something has to determine when to run the GC and so on.
jalf
@Jalf: Indeed. The limitations of Java's GC is the reason why it runs 17x slower than F# on this benchmark: http://fsharpnews.blogspot.com/2010/05/java-vs-f.html
Jon Harrop
I did my own performance comparison: http://www.edval.biz/benchmarking-java-versus-c-with-astar on a smallish, but still significant CPU-intensive program. Amazingly, I found Java to be 30% faster. Since I'm a C++ fan from way back, and a C++ expert, I tried very hard to reverse the results. However, after some pretty comprehensive experimentation, I believe Java is faster. The reason may be the inability for C++ optimising compilers to assume "no aliasing". If you don't believe me, download my source code or try yourself.
Tim Cooper
+5  A: 

To me, this question is a bit of a red herring (perhaps not intentional). Its really the wrong question to ask.

The first questions to ask are these

  1. What is keeping my program slow?
  2. For my new program, what are the key performance design considerations?

Here are some good 'why' questions

  • Is there too much unnecessary I/O?
  • Is too much memory being used?
  • Is the memory allocator being thrashed (too many allocs, too many fine grained object)
  • Is my program blocked on network I/O for long periods
  • Do have locks in the wrong place

I suspect that you really need to focus on the Performance aspects of your program (with a capital 'P') instea od the performance (little 'p') aspects first. If you can get to the point where the language is in the way, then you have done a really good job to that point with respect to performance.

For new code - its important to plan for performance and efficiency up front. I always recomend that performance and efficiency treated just like any other feature (they are features): just like UI bling, or reliability. Of course this will depend on many things - but when its important you need to plan for it up front:

  • Pick data structures and algorithms appropriate for the data set and expected scaling
  • Multi-thread UI based apps where appropriate (UI thread, background/processing thread)
  • Plan for long network I/O latencies
  • Plan to set goals and measure performance up front - run regression tests regularly
  • Measure memory usage - memory hogs are slow (let the japes begin :) )
  • Don't poll when there are events, callbacks or other notification mechanisms

The reason I think this is a red herring is that rarely does one just get to choose between C++ and Java - they are very, very diffrent languages with very different run times. I suspect is is more usual that you have other constraints pushing you one way or other - these will be higher order factors than language performance. Computability with existing code, skills and experience of the exiting staff, etc. etc.

The environment makes a difference too. For example, Java would almost never be the right choice for a widows client (vs. a web) application. Conversely, native C++ would almost never be the choice for a web based app. (note, I am a windows guy - the situation may be very diffretnt in *nix).

Foredecker
+11  A: 

JIT compilers can be faster for many individual code constructs because they can take advantage of runtime profiling of code.

For example, VonC in his answer to this question mentions heap allocation for all objects. This is not actually true: the JIT can allocate objects on the stack if it can prove by escape analysis that references to the object will not outlive the stack frame. In this way, the compiler can get the performance benefit of stack allocation while the programmer can rest assured of the safety of assumed GC heap allocation.

Similarly, Uri mentions virtual functions (called virtual methods in most non-C++ languages). This is another case that JIT compilers have an advantage that is almost never available to ahead-of-time (AOT) compilers: the JIT can insert an inlined cheap type check (a dereferenced-word comparison) and actually inline a virtual method call if that particular call site happens to be monomorphic (i.e. the actual type is always the same in practice). It turns out that up to 95% of all virtual method calls are monomorphic in practice, so this can be quite a big win - and it's a win that is hard for AOT compilers to take advantage of, since runtime code loading may change runtime characteristics dynamically.

Barry Kelly
Is that 80% number made up? I'm guessing that if it were really measured to be that high the coder is using virtual functions for things they shouldn't be used for...
Greg Rogers
No it's not. I got it from Azul's Cliff Click (previously of Sun, and server HotSpot architect). I added a link to the attribution - search for the 95% figure (it was actually higher than I remembered).
Barry Kelly
Note that it's Java that he's talking about, which uses virtual methods by default, i.e. a whole lot more than most other statically typed languages (but on-topic for the question).
Barry Kelly
In theory, depending on how the C++ runtime implements its RTTI, it would be possible to do the same cache lookup check too on all virtual calls. It isn't something specific to JIT compilers. I misunderstood the principle as described in your post - but I can definitely see that having a benefit.
Greg Rogers
It's not so simple, Greg. The Azul-specific approach uses fat 64-bit pointers with class information embedded, so that even an indirection is not required. Similarly, it works for dynamically loaded code, which is a non-trivial advantage for servicing in server code.
Barry Kelly
The approach permits runtime inlining across servicing boundaries, so that third-party libraries - for which you may not even have source - may have your code inlined within them, even when the call is virtual.
Barry Kelly
I thought that the escape analysis was a planned optimization. What VM versions actually implement this? Maybe I got confused that it wasn't due until Java 7.
erickson
http://www.ibm.com/developerworks/java/library/j-jtp09275.html - "the current builds of Mustang (Java SE 6) can do escape analysis and convert heap allocation to stack allocation (or no allocation) where appropriate". I don't know the most current details, sorry.
Barry Kelly
+6  A: 

Yet another bench: the shootout

Gilles
You wont get voted up because your link proves that Java is slower than C++
1800 INFORMATION
Java is slower than C++. That's why I asked the question. Now the question is specifically where is Java slower?
A: 

Some things are better built with Java, C# or any Managed programming languages. Other things will always be better built with an un-managed programming language (like C or C++)

The former category normally includes "applications" in general while the second category normally includes "platforms" in general.

To build FireFox or WebKit in Java is not only just plain stupid but will make the end product become really, really slow, bad and waste a lot of resources for the end users. Open Office is maybe a good candidate for Java, C# or SmallTalk for that matter. But to build FireFox or WebKit in Java (or C# for that matter) is plain stupid and is a failure guarantee...

C++ and C will be several orders of magnitudes faster for many things, in addition to that it'll use a fraction of the memory. That's just the way it is. And as long as Java and C# are "Managed" programming languages this will never change. Maybe someday the CPUs are so fast that "it doesn't matter". But I doubt it since people tend to flex their demands as more CPU is given...

If you want to build browser I am sorry to say that you need to teach yourself C or C++ ;)

Thomas Hansen
+31  A: 

Languages don't have a speed. Neither the Java or C++ language specs specify "and programs must be compiled to be this efficient".

Each language specifies a list of things the program must do, or at least, appear to do, which in some cases put an upper bound on how efficient a program can be, but often, a clever compiler can ignore these rules in individual programs, because all that matters is that the program behaves as if the spec had been followed. Functions can be inlined, heap data can be moved to the stack and so on.

The performance of a program depends on three things: The compiler, the underlying platform/hardware and the program code itself.

Not "the language". The closest you're getting is the compiler.

There are good reasons why either language could be faster than the other. C++ makes fewer promises that could potentially slow down program execution, but Java is JIT'ed, which means it could potentially take advantage of runtime information to optimize the code, which C++ can't easily do... And then again, nowhere in the spec does it say that C++ must not be jit'ed. Just like I believe there are also Java compilers that generate native code instead of JVM bytecode.

Your question only makes sense if you have a specific computer you're running on, a specific compiler for each language, and a specific implementation of your program in each language, in which case you could just run both to see which was fastest.

Garbage collection is another wonderful example. Of course garbage collection implies some overhead, but it also enables some significant shortcuts. Heap allocation is ridiculously cheap in managed languages like Java or .NET, because it is managed and garbage-collected. In C++, it's.... unspecified, of course, but in practice, typically very slow, because the OS has to traverse the heap to find a free block of memory in a more or less fragmented memory space. Which is fastest? Depends on the OS. Depends on the compiler. Depends on the source code.

The source code makes a big difference as well. If you take a Java program and naively port it to C++, it will perform like crap. C++ doesn't deal that well with virtual functions, and usually has superior alternatives available you could use instead. Heap allocation can be very slow in C++, so again, naively reimplementing a Java program would be extremely inefficient. And the same applies when going the opposite way. Many C++ idioms would be needlessly slow if ported directly to Java. So even if you've settled on one platform and one compiler, how do you compare the performance of your program? To even get it to compiler, you have to write two implementations of it, and then it is no longer the same program.

However, I think it's fair to say that on most modern hardware, with a modern Java compiler and a modern C++ compiler, most programs can be implemented to be very efficient, and certainly fast enough. But only if you understand the language you're working with, and play by its rules. If you try to write Java code in C++, then Java will magically turn out to be vastly more efficient, and vice versa.

I guess the most concise answer to your question is "No. No one can quantify performance differences between C++ and Java" ;)

jalf
+1, I was writting an answer in these lines, but not close to this post
David Rodríguez - dribeas
Very good! Even though I do not completely agree I still gave it +1 ;)
Thomas Hansen
+2 for the answer, -1 for exaggerations about C++'s heap and virtual functions = +1
Marcin
It's not an exaggeration. The heap is extremely slow when compared to, say, the .NET heap (which is basically just a push operation on a stack. C++ heap alloc may involve a context switch as well as a linked list traversal. That can be several orders of magnitude slower.
jalf
And I don't see what is exaggerated about virtual functions. Java can remove them at runtime, C++ can't (unless you implement JIT'ing or runtime code modification). That means C++ takes a greater hit from virtuals than Java does. If you make everything virtual, as in Java, you'll feel it.
jalf
-1: Everyone knows that it's hard to generalise about the performance of Java and C++ over all programs, but I get frustrated at how people give up trying. It's a simple question and many people need to get some guidance on this question. On the most popular compilers/platforms, on large programs incorporating many algorithms, what is a good rule of thumb or at the very least a bunch of datapoints (i.e. benchmarks)?
Tim Cooper
I hereby go on record: I believe independent tests on popular platforms show that Java is about twice as slow as C++ on large programs. On small programs (microbenchmarks), Java is still on average twice as slow but with very large variations.
Tim Cooper
@Tim: It's not about generalizing the performance over all programs, but over all programs, compilers and computers. And it's not about "giving up", but rather realizing that the answer isn't useful, and there isn't a simple good rule of thumb.
jalf
I think in the real world (real apps doing real things) well written C/C++ will outperform managed languages. Yes it's true in theory heap allocation in gc is cheap. However a competent C++ dev wouldn't put everything on the heap!
seand
+1: Good explanation about language comparison in general; -1: Heap in C/C++ is managed in userspace thus it's as efficient as Java heap; -1: calling virtual functions in C++ are as fast as using function pointer. Also, callers are also inlined in most optimizing compilers thus Java can perform no better than C++ and usually is slower.
buratinas
The heap in C++ isn't compacted like it is in Java/.NET, which means it is much more expensive to find blocks of memory to allocate. Virtual functions are roughly as expensive as function pointers yes (actually, there's one more layer of indirection with virtual functions, but it's close enough), but I never said function pointers were fast either.
jalf
And in C++, virtual functions often are *not* inlined, because at compile-time, it is typically difficult to see which function would be called (if only one function can be called, you probably wouldn't have made the function virtual). And yes, Java can be faster than C++. So -1 yourself ;) why is it that so many programmers make it a religious issue that "C++ must always be fastest, right? Right? Otherwise what's the point in anything?"
jalf
+4  A: 

Some points to take into account:

  • If you get a better C++ compiler, your code doesn't become faster. You need to recompile it first. If you get a better JVM, all your Java code will run faster

  • If you get a better C++ compiler/JVM, you will see 10-20% faster execution, usually in corner cases. If you find a better algorithm to achieve what you need, you can easily get 1,000%-10,000% more performance, sometimes even more.

So today, if performance is an issue, you should look at these two facts:

  • How easy does the language make it to replace one algorithm with another? (a.k.a "Refactoring")
  • How fast can you write code in it?

Anything else is just FUD.

Aaron Digulla
+3  A: 

What many people forget is that JIT techniques can be applied to any kind of binaries, even those produced by a C++ compiler. Most of the benefits of JIT compilation for Java are also valid for C++ if you use something like HP's Dynamo (an emulator that runs executables faster than the native chip it runs on and emulates). Runtime profiling is not really a performance advantage of Java, but of JIT compilation in general.

Koen Van Damme
+2  A: 

I have implemented performance-sensitive applications (physical simulations, financial models) in both C and Java. The reality is that I've always got much larger gains in performance by changing the algorithms than by tweaking the implementation -- but the implementation also matters. As for now, my opinion is that Java is slower than C (I don't have that much experience with numerics in C++), but a lot can be gained by careful tweaking, and this tweaking is a lot easier in Java, since you don't have to deal with segmentation faults, double frees, etc. C++ occupies the middle ground here, as modern C++ techniques (smart pointers, templates, STL containers) offer both speed and relative safety of use.

quant_dev
A: 

Java apps have an initialization overhead that C++ programs do not. When JITed, they are not micro-optimized as much as C++ programs. Also, there is a small runtime overhead (GC + indirect call overhead). Overall, these quantifiable differences don't add up to much. But...

It's well known that when a Java app first starts, it must activate its flux capacitor to bring it's environment back to 1995. This introduces a little delay in startup. But once that's over, the JVM performs about as well as a comparable C++ program running on hardware from 1995.

Frank Krueger
+1  A: 

Where does Java fall short when compared to C++?

Excellent question. Java and the JVM have two main deficiencies that cripple performance compared to C++:

  • Generics based upon type erasure.

  • Lack of value types.

The former means that generic code incurs boxing and unboxing which incur massive amounts of unnecessary allocation and extra levels of indirection that are cache unfriendly.

The latter means it is impossible for the programmer to unbox arbitrary data structures like complex numbers (pairs of floats), hash table entries (key-value pairs) and vertex data.

Both of these problems combine to make it impossible to implement an efficient generic hash table in Java. In particular, .NET solved both of these problems. For example, Java's generic hash table can be 17× slower than a .NET Dictionary.

In addition, JVMs have very slow FFIs compared to C++. I've heard that simply invoking an external C function from Java can take 1,000 cycles.

Jon Harrop