This is not really true, at least not as such a general claim.
1. malloc()/free() can be either faster or slower than garbage collection. It depends on implementation details and is situational. Note in particular the issues of memory locality and temporary allocations.
2. This assumes an omniscient programmer who has perfect knowledge of when to allocate or free. In reality, memory management is a traditional cross-cutting concern, and in order to deal with it manually in a modular fashion, you will typically introduce additional overhead. Examples:
- in C++, m[a] = b, where m is a map, and a and b are strings requires that both a and b are being copied. This is not necessary in a GCed language.
- naive reference counting has significant overhead, significantly more than a modern tracing GC.
- even unique_ptr has overhead (though less so than reference counting).
Garbage collection allows you to have the necessary global knowledge to (mostly) eliminate memory management as a cross-cutting concern, because the GC is allowed to peek behind the scenes and ignore abstraction boundaries.
3. Things that C is fast at is usually also allocation-free code, i.e. iterating over arrays or matrices. The performance of such code is not going to be any different in a GCed language, assuming an optimizer of comparable caliber.