There are arguments that GCs can be faster, yes, but that speed almost always comes with an increase in memory usage not a reduction. After all asynchronous periodic collection must necessarily increase the transient working set of memory used over immediate synchronous collection.
The advantages of a GC here in typical contexts are that GC'd languages usually allow for compaction which can reduce fragmentation. But this isn't an inherent benefit of a GC. You can have a GC'd language where you don't get this benefit, though, it's not an inherent property of the GC itself.
For example D is a GC'd language, but because D's allocations are allowed to interop with C libraries you can no longer do compaction. There's thoughts on how you could do it with automatic pining but it's not done currently. But either way it's really the lack of raw pointers that make compaction possible, not whether or not you have a GC.
Such are the tradeoffs with a conservative garbage collector.
I would avoid Boehm GC (and other conservative GCs) in almost all situations.
Yes, on 32-bit platform false pointers are a problem esp as you get closer to 1g for instance.
On the other hand on 64-bit I’ve never seen it at all. The chance of arbitrary long/double to point to some object in the heap area is 1/2^32 smaller and that turns the problem from common nuisance to purely theoretical problem.
Just to further clarify the terms if someone is looking for more info on this:
In the context of system memory people mostly refer to this as compaction and not defragmentation.
So I would think this requires some compiler support or some sort of runtime.
If you know more about this or know any cool implementations of it please elaborate!
We already have this - almost all modern computers have something called virtual memory, that allows you to de-couple your memory addresses from where the memory actually is. This allows you to 'move' memory without changing the addresses that you use to refer to it. You can then defragment memory by mapping two sets of addresses to the same memory physical memory, as long as the holes in the two sets overlap.
In order words, if you have two pages, one with only the first half used, the other with only the second half used, you can copy the used part of the second page into the gap in the first page, and map the old addresses of the second page to the location of the first, now shared, page. You are using twice the address space (which costs just a few bytes in bookkeeping) but have defragmented so you're only using half the physical memory.
You can then completely return the second page, now un-used, to the kernel.
I would think the page level granularity of virtual memory makes it not that useful for this purpose, since the used and unused parts of the two pages would have to line up nicely and larger objects tend to cause less fragmentation.
Fragmentation is often just one pesky object holding onto a whole page. If you have many such pages all with one object it's likely you can map them all together and release most of them.
Their algorithm also addresses your concern of how to make pages “line up”.
This method’s likely subject to the criticisms around this post.
A core benefit of GC is you can have pretty complex memory management techniques that run more or less totally transparently. You can leverage generations (or defragmentation) to keep allocation latency low, etc.