"Imagine doing lots of small allocations - you can cause a lot of fragmentation resulting in needlessly having to resize your heap which in dire scenarios can result in thrashing."
The article repeatedly talks about how managing memory manually increases the risk of fragmentation. And that this risk somehow goes away with gc managed heaps.
...so garbage collectors don't also have to manage their own internal heaps and have fragmentation issues? Hm, not sure I buy this.
Compacting garbage collectors don't have fragmentation issues, but of course Go doesn't have one. A GC isn't even strictly a prerequisite for compaction. Manually combining memory allocations to reduce allocator overhead and fragmentation is a lot of work, but not unheard of.
The Classic Mac OS API (the "toolbox") had a compacting manual memory management scheme. Instead of raw pointers like what malloc might return, you worked with double-pointers called Handles (different from Win32 Handles), which indirected through a global Handle table. System calls may compact or rearrange the blocks of memory referenced by Handles. If you wanted to dereference the Handle across a system call, you had to HLock it to keep it from being moved, similar to object pinning in C#.
In modern OSes, virtual memory plays an analogous role. We still have a double indirection, but it goes through the TLB and page table.
The article repeatedly talks about how managing memory manually increases the risk of fragmentation. And that this risk somehow goes away with gc managed heaps.
...so garbage collectors don't also have to manage their own internal heaps and have fragmentation issues? Hm, not sure I buy this.