3 ms·
I think that's the other side of the same coin - GC lets you write more efficient code (for certain definitions of efficient) by default, but they're always pos
by GeneralMayhem 4y ago
I think that's the other side of the same coin - GC lets you write more efficient code (for certain definitions of efficient) by default, but they're always possible to beat if you're more aware of lifetimes and manage them explicitly. GC is an easily achieved local maximum; badly written or unoptimized non-GC code (e.g., making everything a shared_ptr in C++) will be worse, while well-written non-GC code will be better. That may well be the right tradeoff most of the time, where either the delta between the absolute and local maxima is small or the effort it would take to surpass GC is too great, but there are occasionally workloads or patterns that are very easy for a human to optimize but hard for a generic GC.
> how do you know when to clean up the memory?
Right, you have to pick a time that's optimal for your application. It's not trivial, but a GC would only be able to take a guess, whereas the developer can know based on the program's logic when an optimal time is - for instance, at the end of a request in an RPC server (https://developers.google.com/protocol-buffers/docs/reference/arenas https://developers.google.com/protocol-buffers/docs/referenc...).
> Using something like a reference count adds contention to this high-concurrency data structure, slowing it down
I rarely find this to be true. If a thread is going to be repeatedly requesting access to a structure, it can usually hold the reference throughout. If there are lots of ephemeral threads that independently need to grab refcounts, usually there's a higher level coordinator that's spawning them that can own a single reference. If you really need to do something like a mark-and-sweep, there's usually a custom way to do it that's more efficient than a generic GC would be (e.g., with generational immutable data structures, if you can guarantee that versions are referenced in order, then if the min version referenced is N, you can immediately drop all versions <N without needing to do a full sweep.
- mike_hearn 4y agoThe developer can only know this to the extent that they control everything happening in memory. The moment libraries maintained by disparate teams enter the picture especially if they are binary-only or otherwise encapsulated, defensive coding starts because you can't reason about lifetimes across the whole program anymore. It also massively complicates any API surface as now every API must declare its refcounting and ref holding rules. GC gets rid of all of that complexity because the GC actually does see the whole program.