Describe Go's memory allocator: size classes, mcache/mcentral/mheap, and the tiny allocator.
Question 335HardGo 1.22 to 1.25
The allocator is derived from TCMalloc:
- Size classes: there are about 68 of them, covering objects up to 32 KB. Each request is rounded up to its class, so a 33-byte object takes a 48-byte slot. Objects larger than 32 KB get their own dedicated span straight from the heap.
- Spans (
mspan) are runs of 8 KB pages, each split into slots of a single size class. Separate spans are kept for "scan" objects that contain pointers and "noscan" objects that do not, so the GC can skip noscan memory entirely. - mcache: each P has its own cache of spans, one per class, so the fast path takes no lock.
- mcentral: a shared pool of spans per size class, used to refill mcaches.
- mheap: the global page allocator, which gets memory from the OS.
- Tiny allocator: noscan objects smaller than 16 bytes, such as small strings or
int32values, are packed together into one 16-byte block. The whole block stays alive while any of those objects is reachable, which is why finalizers on tiny objects may never run.
Interview angle: rounding to size classes explains why append growth "overshoots", for example cap becoming 6 or 8 instead of exactly double. Keeping pointers out of large structures means the GC has less to scan.
More on Memory, GC & Runtime Internals
- Q333List the common reasons a value escapes to the heap.
- Q334How do goroutine stacks grow, and why does that constrain the language?
- Q336Explain Go's concurrent tri-color mark-and-sweep garbage collector.
- Q337What is a write barrier and which one does Go use?
- Q338Walk through the phases of a GC cycle. Where are the stop-the-world pauses?
- Q339Is Go's GC generational or compacting? What is the "Green Tea" GC?