|
In the general case, virtual dispatch has an overhead in both C++ and Java (which btw is only <5 machine instructions), but it's true that Java can sometimes eliminate it with runtime information, which C++ can not use. However, in my experience, using virtual dispatch is a relatively rare ocurrence in C++ (compared to the vast majority of method calls). On the other hand, on Java, most of _everything else_ is indirect and has overhead: All objects are allocated on the heap, primitives (int) are often objects (Integer) where they ought not to be, all objects have 16 bytes of overhead, etc. But the JVM will convert those heap allocations to stack allocations! And it will realize those Integers are used as int and remove the overhead! And it will realize you're not using the information on the header of every object! Perhaps in synthetic benchmarks, but in real programs, where there are an almost infinite amount of code paths, dumb 'data transfer' objects are common and things need to be modularized, the JVM is forced to assume the worst case can happen (even if you as an human can prove that it won't happen) and inhibit those optimizations. And now you have indirect accesses everywhere, memory overhead (=cache trashing) everywhere, the runtime can't vectorize that tight due to Integers, etc. In fact, I can't think of any domain where there is heavy competition and where high performance is a determining factor where Java has won to C/C++. In browsers, it certainly has not. |
The number of instructions is much less important than what they are doing. In the case of virtual dispatch, it's doing a memory lookup. If that memory is in cache it could be relatively inexpensive but not guaranteed. However, if you have to hit main memory then things are much slower.
> But the JVM will convert those heap allocations to stack allocations!
I was surprised recently to learn this is not the case. (at least, not with hotspot) The JVM will try and "scalarize" things (pull the fields out of the object which may push them onto the stack) but it won't actually allocate a full object on the stack (OpenJ9 will, but I don't see people using that very often).
It is also somewhat bad at doing the Integer to int conversion. That is mainly because the Integer::valueOf method will break things (EA has a hard time realizing this is a non-escaped value). Simple code like
can screw up the current analysis and end up in heap allocations.There is current work to try and make these things better, but it hasn't landed yet (AFAIK).
> In fact, I can't think of any domain where there is heavy competition and where high performance is a determining factor where Java has won to C/C++. In browsers, it certainly has not.
I think the realm where the JVM can potentially beat C++ is, funnily, work that requires a lot of memory. The thing that the JVM memory model has going for it is that heap allocations are relatively cheap compared to heap allocations in C++. If you have a ton of tiny short lived object allocations then the JVM will do a great job at managing them for you.