The thing is that most garbage generated is thread local. In fact, depending on the program, it's likely that most of it follows a stack discipline, albeit one that's not delimited by function boundaries.
A simple GC (or resettable arena allocator) can make use of this knowledge, and be quite a bit faster in those specific cases.
It's hard to beat the man years of work in generic GC that works in all cases, but it's not that hard to beat it in specific situations when the application author knows the details of how the application will do the allocations.
99% of the time, writing your own custom allocation strategies is a waste of time. Sometimes, though, it can be a win, allowing you to allocate and free in a matter of tens of CPU cycles with no GC pauses at all.
>99% of the time, writing your own custom allocation strategies is a waste of time. Sometimes, though, it can be a win, allowing you to allocate and free in a matter of tens of CPU cycles with no GC pauses at all.
Agreed, but again, if you're willing to put that effort in you can do it in a GCed language.
This is hardly the case, especially on modern multi-core hardware. Writing a GC that works well in a concurrent environment is a huge undertaking. And unless your system is very simple, you'll often be better off with a good general-purpose GC.
A shared_ptr introduces a lot of contention.