If you're doing application development then UI performance is usually good enough using modern runtime environments and libraries. When this is true being able to release features quickly is the most important metric.
But if you're working on a 3d game engine, writing a web browser, writing code on an embedded platform or writing a database then performance itself is a feature. Being lazy with allocation or your choice of algorithms is a really expensive mistake that will hurt your bottom line.
Nothing is absolute, there are always tradeoffs. If everything was a one-size-fits-all solution then Software Engineering wouldn't exist as a career.
The reason is that whoever wrote the GC for your language has to solve an extremely general problem for an extremely large body of users with very different use-cases.
A memory management system for a particular program only has to solve the problems of that program, which is a tremendously simpler thing to do.
General-purpose GCs are like the F-35 or Space Shuttle ... due to the broad nature of demands they are very complicated, and are much more expensive and perform more poorly compared to specific solutions.
I don't like to sound rhetorical, but writing a memory management system for anything non trivial (that is, a scenario where you allocate and deallocate memory) quickly becomes a difficult problem.
Besides, could you give us an example ? I'd like to know about it. My example is a video game where we were allocating thousands and thousands of small stuff and deallocating it. Soon you end up with a fragmented memory where you can't allocate big chunk of memory...
Other common trick in video games is to have a single-frame arena allocator for objects that are transient frame to frame. You just move a pointer forward and reset the pointer at the end of the frame.
It's also odd because you're replying to a well-known game designer.
That said, there are allocation-heavy workloads for which GC is well suited.
Authority position ! :-) I worked on optimizing the Outcast game 3D engine (ok that was around 20 years ago). And I clearly remember other devs in the team struggling with memory allocation.
In the end, they sorted it out without resorting to a full fledged GC. But since our case was simple (loading resources for building a world, then releasing resources that are not useful anymore), I concluded that it's not easy.
In the end, it all depends on the nature of the problem, and one can optimize for any of them (as it is customary in video games). I know that.
Writing a generic memory management system is non-trivial.
Designing and implementing a memory management strategy with an understanding of the application semantics--especially when you can modify the semantics, or enlarge or narrow the relevant context, as appropriate--is much easier. Trivial in many cases.
Writing a GC for the JVM is difficult because the 1) JVM has far fewer degrees of freedom, and 2) they have to solve a much more difficult problem. All those awesome-sounding automatic optimizations JIT compilers can implement pale in comparison to the overall difficulty of the underlying problem.
By way of analogy, look at formal software verification. The underlying computational complexity of the algorithms are extremely costly. The only way to make it work is by using a human to refactor the big problems into many smaller problems, including smaller problems that encapsulate other smaller problems. Only humans can do that, and it will be that way for quite some time.
Manual memory management is the same way--a human can do better than a generic collector because only the human can refactor the program. Only a human can say, "this part is too complex, with too many lifetime and ownership interdependencies, so I'm going to refactor it so it's easier to use a more elegant memory management strategy". Generic collectors like those in the JVM can't do that--they have to work with the software they're given.
If you're having trouble with memory management, perhaps it's because you haven't yet figured out that you don't need to play by the same rules as an automatic garbage collector. And you certainly don't need to be, nor should you be, restricting yourself to a malloc/free-like interface.