Not necessarily, it depends on your allocation patterns. The same can be said for using malloc.
> Not to mention, it has no idea how your program uses memory, such that it is bound to use a generic approach
Ditto for malloc.
> with manual management, you can get real and high performance.
Using a GC does not mean you can't manually manage allocations. E.g. say you are allocating and deallocating a lot of Point objects. You keep a free list of Point objects that you can recycle. If you need a Point, you first see if there are any in the free list. If so, you pop the first one off the list and reuse it. Otherwise you allocate a new one. When you're done with a Point, you push it on the free list.
> Ditto for malloc.
malloc != manual management
> Using a GC does not mean you can't manually manage allocations. E.g. say you are allocating and deallocating a lot of Point objects...
But that's not using a GC. It's manual memory management.
> If you use malloc willy-nilly throughout core algorithms, your runtimes become unpredictable.
First, where did I say "use malloc willy-nilly"? Second, do you have experience with that? I haven't much, but I haven't heard your claim before.
Of course "willy-nilly" should not be done with real-time constraints. But I have written a substantial algorithmic program (no RT constraints) in that style when I didn't know better, and it was very well performing. (probably glibc's malloc was optimized for my allocation patterns).
The main problem I see with that style is that each malloc has memory overhead, and that it leads to unmaintainable code.