What the quote describes:
split into 16/32/64 byte chunks
That is:
a memory pool (slab allocator)
- very simple
- fast
- good for learning
- not a general allocator
What you originally wanted:
one big memory region -> split dynamically based on request size
This is:
a real free-list allocator
- variable sizes
- splits blocks
- merges blocks
- used in real systems concepts
Building a free list allocator, splitting allocator to allow for variable size allocations. The fixed one is good for memory pools.
t.Errorfmarks test as failed but continues executiont.Fatalmarks test as failed and immediately stops (callsruntime.Goexit())
- Walk free list, find node matching the offset
- Set
Free = true - Check next block (address + size) — if free, merge into current
- Check prev block — if free, merge current into it
- Merge by address adjacency, not list order
- Not the allocator's job to zero memory on
freeoralloc - After
free: user must not touch the memory — if they do, it's a use-after-free bug - After
alloc: returned bytes have unspecified content — caller must write before reading - Reading uninitialized memory is the caller's bug
- This matches the
mallocstandard contract - Zeroing on free would be O(n) overhead and defeats the purpose of a fast allocator
- If zeroed memory is needed, the caller does it explicitly or uses
calloc
Walk the list and take the first free block that is big enough.
[50][100][200]
Request 80 → [50][used][200]
Fast because you stop at the first match.
Walk the entire list and pick the smallest free block that fits.
[500][90][200]
Request 80 → [500][used][200]
Picks 90 over 500 and 200 — minimizes waste per block, but slower (full scan).
Take the largest free block.
[50][100][200]
Request 80 → [50][100][used(80)+free(120)]
Leaves the biggest remainder, which can help with fragmentation in some workloads.
- An arena is just a
[]byte— the allocator manages slices of it - Metadata (
MemBlockwith offset, size, free flag) lives separately from the arena - A free list tracks which chunks are available using a linked list
- Splitting divides a block when the request is smaller than the block
- Coalescing merges adjacent free blocks back together to avoid fragmentation
- First-fit is the simplest allocation strategy
- Offsets into the arena work because we never move blocks (no compaction)
- Freeing does not return memory to the OS — the arena is fixed
- The caller is responsible for initializing memory — the allocator does not zero