I love this topic; can't resist chiming in. There is indeed a lot of
misinformation out there about "manual memory management". I believe
all the gains (if any) to be had from manual memory management come
from (1) requesting stack allocation (it can be hard for a compiler to
prove that the lifetime of an object is limited enough for this to
work), (2) reusing space efficiently by overwriting it.
(1) mostly applies to small objects. We handle it by providing
immutable objects, which are much easier to automatically stack
allocate. We can't yet stack allocate all immutable objects, but work
has been done on it and we'll get there eventually. Also due to
stack-bounded lifetimes, these objects are likely to become young
garbage that GC is especially good at handling.
(2) is possible in any language with mutation. Overwriting data is a
form of manual memory management (you're saying you don't need the old
version of the data any more). In Julia folks get speedups from this
all the time. While I'd love it if we could get that level of
performance automatically, in the meantime this is a highly effective
form of manual memory management that's fully compatible with GC. So I
get annoyed when somebody says languages should have manual memory
management *instead of* GC (which fortunately nobody argued here). If
you're willing to use manual memory management techniques, a GC isn't
going to slow you down! And Yichao is right that for a given heap
allocation workload, GC handily beats malloc/free (since the gains
come from reusing space and avoiding heap allocation, not from
malloc/free being fast). I suspect a lot of the confusion is due to
languages with GC tending not to offer in-place algorithms and other
kinds of support for mutation, even though they could.