I don't you need to be particular smart using manual memory allocation to beat GC. You just need to free your memory once you're done with it. Consider:
for (size_t i = 0; i < 100000000; ++i) {
size_t* val = malloc(sizeof(size_t));
*val = i;
free(val);
}
Decent memory allocators will just keep reusing the same memory location over-and-over. All 100 million calls to malloc and free will be fast-path calls. GC-based schemes will most likely not be 100 million fast-path allocations. Yes, this is a contrived example, but freeing memory as you no longer need it is common in languages with manual memory allocation. It is also harder, more error prone, and quite often leads to nasty bugs, but it's usually faster.
I think you're reasoning about just the cost of the frees versus garbage collection cost. But by ignoring the extra memory required on the heap, you're also ignoring the extra slow-path allocations.