Articles

Java versus C++ Performance

Recently, I came across an interesting discussion of C++ versus Java performance over on Stack Exchange. There was also some good discussion of the article on Reddit which included a link to an interesting article from Google.

Understanding these languages from a performance perspective is important to me, as it impacts the design of Whiley. So, I thought I’d highlight the main strands from that article and the subsequent discussions, and also add a few points I think were missed:

  1. Memory Usage. Accessing RAM has become relatively slow as CPU performance has increased and, hence, memory utilisation is extremely important in practice.  Java fairs quite badly on this front since: a) every object occupies at least 8 bytes; b) you can’t stack allocate objects; c) the commonly used collections library forces most things to be an object.  Also, arrays of objects in Java are really arrays of references and, hence, cannot be allocated contiguously — which hurts cache performance.
  2. Garbage Collection.  This is a common complaint against Java performance.  With explicit explicit memory management in C++, you can tightly control the process of allocating and deallocating memory.  This means, for example, large chunks can be allocated up front and pooled.  And, also, that long-lived memory imposes minimal overhead.  However, there is one C++ performance problem I have encountered here: memory fragmentation.  The garbage collector is constantly compacting used memory into a contiguous block — which can really help performance.  In contrast, for long running applications in C++, memory can become severely fragmented which affects both allocation time and cache performance.  Particularly if the amount of allocated memory at any one time fluctuates significantly.
  3. Language Specification.  The Java Language Specification is much more specific on the order in which Java programs are executed.  For example, that expressions are always executed in left-to-right fashion.  In C++, there is more flexibility in terms of implementation — which makes things harder to debug, but also gives the compiler more freedom.  Personally, I think the Java Language Spec is really a step in the right direction to ensuring software quality (i.e. that there are no unexpected surprises), so I’d be happy to live with this cost.
  4. Execution Model. There are advantages to using a Virtual Machine with Just-In-Time compilation (i.e. Java), compared with a static compilation model (i.e. C++).  In particular, a virtual machine can optimise according to the current workload of the program.  In contrast, a static compilation model has to guess ahead-of-time what the workload will be, and where optimisation should be focused.  This causes problems because some optimisations (e.g. inlining) negatively impact performance if used pervasively.  To combat this, modern C++ compilers now support profile guided optimisation which helps mitigate this.  Nevertheless, on long running programs which have varying and unpredictable workload behaviour, the JIT should (in theory, at least) have an advantage.  Web applications might be one area where this holds true, although it’s unclear to me how well current JIT’s adapt to changing workloads (i.e. will they actually undo an optimisation when it no longer makes sense?).

My general feeling is that performance remains a critical issue for language design.  Many people say “machines are fast enough” or that “with a sufficiently smart compiler…“, etc.  In practice, these things never come to pass because the goalposts themselves are moving.  For example, web applications must routinely scale up to millions of hits a day (or more), compared with tens of thousands only a few years ago.  And, in the future, we’ll demand even more.

Finally, the focus on memory utilisation as a fundamental performance bottleneck makes me question the future of pure object-oriented languages.  Today, these language appear to be back in vogue (e.g. Scala, Ruby, etc).  But, I just wonder whether these languages will be able to deliver the performance needed for the future …

Thoughts?

18 comments to Java versus C++ Performance

  • Java can be as fast or faster than C++. The garbage collection point is interesting because people can see and measure the time the gc takes in Java. In C++ is it hidden. So, people think of C++ code as not having a memory collection overhead. Interesting, if one moved over from using raw pointers to using shared_ptr the performance of C++ becomes very poor in this regard.

    The place the Java really struggles is in real time, soft or hard. C++ is much better at this. So, if your language is to be able do stuff like real time audio processing, machine control, real-time trading, then a lower level implementation like C++ might be a good way to go.

    From this article, I get the feeling that you could do with learning quite a bit more about how virtual machines work before going one direction or the other. Also, what ever you do, do not write your own VM!

  • Isaac Gouy

    Java can be as fast or faster than C++

    Please provide example programs, and state how to run them so the Java program is as fast or faster.

  • Taf2

    Java is implemented in c++. Nuff said

  • > The garbage collection point is interesting because people
    > can see and measure the time the gc takes in Java. In C++
    > is it hidden. So, people think of C++ code as not having a
    > memory collection overhead.
    Here’s a great quote from Bjarne Stroustrup:

    “C++ is my favorite garbage collected language because it generates so little garbage”

    Stack allocation saves C++ from a lot of the problems other languages suffer in terms of garbage collection.

    > Interesting, if one moved over from using raw pointers to
    > using shared_ptr the performance of C++ becomes very poor
    > in this regard.

    The runtime overhead of shared_ptr is small in comparison to the allocation and deallocation of said memory. Yes, there are some atomic increments here and atomic decrements there — which can cause problems with multi-threaded code. But neither is there a good more performant alternative to shared_ptr for reference counting. The benefit that C++ has is deterministic destruction of shared_ptr’s. When something is really no longer used, it is destructed. With Java, the finalize method only gets called when the GC gets to it. There’s no knowing when that will happen. If you need something more precise, then you have to implement your own reference counting in Java. Yuck!!!

    Now, it you don’t need reference-counting, in C++ you’d use unique_ptr or stack objects. Niether of these suffer the costs of atomic operations of shared_ptr. The shared_ptr should only be used if you *need* reference counting.

  • Greg

    ‘Java is implemented in c++. Nuff said.’

    This is a bad argument. c++ is implmented in c. c was implemented in fortran. They are all compilers that all eventually compile to native assembly, not source code of the implementing language. The efficency of the implementing language has nothing to do with the speed of the assembly that the compile generates.

  • Ben

    “Java can be as fast or faster than C++”
    You don’t know how Java or C++/C works. If you are comparing a shitty code written in C++ than you are no longer comparing languages but the programmers. Java is not as fast as C++ or C, because C++/C is register based and Java is stack based. So, stop dreaming. There are also plethora of other truths that show how Java cannot be as fast, yet alone faster, than C++/C, some of which were already mentioned in this article.

    Java is great for portability. However, if you only need speed, then Java, obviously, isn’t the answer. Any okay programmer knows this.

  • karlix

    How often do you personally program a web-service that has to scale up to 1kk requests a day?

  • André Pankraz

    @Ben…stack based as reason for slower Java is a none-argument.

    Interpret the stack as registers s0, s1, s2… and “store 2″ is “r2 = s_top”, “load 1″ is “s_top++ = r1″ etc.
    And there you have your direct register-based model. The JIT optimizes this “load 1 load 2 add store 2″ to more compact assembly equivalents.

    and for that “obviously” and “any developer knows” – i stick to facts, e.g. participate in http://shootout.alioth.debian.org/ and provide optimal / compareable implementations.

  • About the “Garbage Collection” point: I think your comparison is a bit unfair. Java does (or tries to do) the garbage collection for you. In C (and its derivatives) you have to do it yourself – and often programmers forget to do that, resulting in bugs and out of memory problems in native C applications.

    Native C applications require a lot of attention when it comes to memory management, as the compiler really does nothing for you.

  • chrisreichel

    This is just a matter of trade-off: Do you want maximum control of RAM and manage pointers or you want some less strict control over memory and a small decrease of performance.

    You should consider also consider other aspects like productivity. With more abstractions over the languages you got less performance.

  • Hi Itoctopus,,

    In C (and its derivatives) you have to do it yourself

    True, but this is not really about performance per se, rather you’re talking about the advantages from a software quality perspective …

  • Ankur Varsheny

    From my experience 99% code written in c++ will be much faster then Java. And all code written in C has always been much faster to me then C++. People use C++ for some extra benefits it gives over c++ and same goes for Java. Java is little slower but gives more flexibility and robustness. C++ is a very unsafe language, it gives you all the strong tools to attack but not to defend. I have spent countless hours debugging stupid heap and stack corruption problems over last 10 years which could have been spent in something more useful.

  • sarabjeet

    i really like that you are giving information on core and advance java concepts. Being enrolled at http://www.wiziq.com/course/1779-core-and-advance-java-concepts i found your information very helpful indeed.thanks for it.

  • Dave,

    Here is another article:

    Performance of Java versus C++
    http://scribblethink.org/Computer/javaCbenchmark.html

  • JCoder

    “The runtime overhead of shared_ptr is small in comparison to the allocation and deallocation of said memory.”

    This is funny how some proponents of C++ don’t know the real costs of things they are using. The overhead of interlocked operations is negligible only on your desktop home computer with one physical core (and 2 virtual ones). But the cost is enormous in massively multithreaded applications run on a 16+ core multiprocessor, NUMA machines. Additionally a shared_ptr occupies usually 16 or more bytes of memory, so this is a huge cache-killer compared to a 4-byte pointers in Java, which can address 64 GB or RAM. So no, shared_ptrs are not a solution for lack of proper GC in C++. They are also harder to use.

    BTW: Allocating and deallocating dynamic memory in C++ is also much slower than in Java. In Java allocation is one simple check and moving a single pointer (it is very close to stack allocation speed), and deallocation cost is exactly 0 for most short-lived objects. No C++ general-purpose allocator can rival that. And cost of GC is really low nowadays – if it is correctly tuned, it doesn’t exceed more than 5% of overhead. In some application the problem might be pauses, though, but those problems exist in C++ as well. Destroying a long chain of smapr_ptrs may cause a sudden pause, too.

    As for the RAII, it is an awesome win compared to raw C, but not compared to Java. Java has automatic resource management blocks and try-finally construct which allows for deterministic release of resources.

    Java Hotspot can inline calls across dynamic module boundaries, C++ compilers can’t. Java can inline virtual calls, C++ can’t, except in trivial cases where it doesn’t matter.

    Many other well known optimizations are done by both: loop unrolling, SSE vectorization, proper register allocation, etc.

    So, it very much depends on what program you are writing, but if Java is slower or faster by more than 50% than the C++ equivalent, you are obviously doing something very wrong. In most cases such performance differences are just programmer inability, not differences between languages.

    And another important thing: the best speed improvement comes usually from algorithmic high level / architectural optimizations, not from low-level bit twiddling. While you can do that in any language, Java (or better: Scala) is a much nicer tool to work with and offers lot more than STL and Boost, especially for parallelization and lockless functional style of programming.

  • [...] C++. Here are some discussions: C++ performance vs. Java/C#  Performance of Java versus C++   Java versus C++ Performance. But Java seems always have more memory footprints than C++ and this is what I concern. Since the [...]

  • GregB

    Whoever said C is implemented in Fortran hasn’t got a clue.

  • dominique

    So this is my comments, for the coders who daily deal with finance programming and Russian hackers, the answer is simple : C++ is more efficient, more secure and more precise than Java.
    It takes months for an hackers to reverse a C++ code (some time never) than 48 to reverse a Java one.
    In big player banks when it come to code very precise algo for market trading, every one turn first to the C++ boyz, then the Java’s.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>