Jimmy said:
but why almost all benchmarks I remember point to a much slower
memory allocation perofmrance for JVM vs C++
If you've found even *one* worthwhile comparison of GC memory allocation vs.
explicit then you've done better than me. Any links ?
The problem is that the two memory control techniques result in different
programming styles. The obvious example being C++'s STL where objects are
*copied* into the containers rather than being pointed to by the containers (I
know you can put pointers into containers, but that requires you to have global
knowledge of the lifetimes of the objects pointed to -- which isn't always
available).
So in comparing, say, Java and C++ for memory allocation alone, you still have
to compare two apps written in *different* styles, which makes it very
difficult to isolate the effects of memory allocation.
Another thing you should remember is that it's difficult to do micro-benchmarks
for memory allocation. In typical generational GC, the algorithm is tuned for
certain broad assumptions about object lifetimes and access patterns. Those
patterns are difficult to reproduce in a micro benchmark (though you can make
rough approximations). OTOH, in C/C++ if main() just allocates 1M 20byte
objects, then it will be allocating them from unfragmented space, which is a
very poor reflection of normal runtime behaviour.
However I *suspect* that if you could control for all that, then you'd find
that GC is quite a bit faster for typical apps (ones where most data is not
long-lived). Reasons for thinking that:
- Java (like other languages with GC) places heavy load on the GC mechanism,
hence the implementer will tend to put a lot of effort into state of the art
allocation. Whereas in C/C++ dynamic memory management has typically been seen
as something that doesn't happen much (relative to the overall runtime) and
there is relatively little attempt to tune it.
- Theoretical considerations like the number of instructions needed to allocate
an object. (Though you must remember that the total runtime of an app is
influenced by every object that survives *any* GC -- in an ideal world (for a
GC implementer) *no* objects would ever survive. OTOH C++ has the copying and
fragmentation problems.)
- The practical observation that object pooling is still a very popular
technique among C++ programmers who need to squeeze optimal performance out of
a machine. (And indeed I've found it very effective myself). Whereas the
technique is not popular among programmers using languages with good GC
implementations, such as *modern* Java. (You'll still find the advice to use
object pooling in Java here and there -- it's a hangover from the days when
typical JVMs used GC implementations which were little better than jokes. I
don't think any experts are still advocating it as a general technique for Java
(it can interfere very badly with GC), though it is still a technique to bear
in mind for special applications). The relative popularity (and effectiveness)
of the technique suggests that the C/C++ memory allocation is quite a lot
slower than good quality GCed allocation..
-- chris