The Slab Allocator: How the Kernel Avoids Fragmenting Memory for Million-Object Workloads

2026-06-18

The buddy allocator hands out memory in power-of-two pages — fine for large allocations, terrible for the kernel's actual workload: millions of tiny, fixed-size objects (task_struct, inode, dentry, network sk_buff). Allocating a 4KB page for a 320-byte task_struct wastes 92% of the page and fragments memory within minutes. The slab allocator sits on top of the buddy allocator and solves this.

A cache in slab terminology is a pool dedicated to one object type and size. Each cache owns slabs — contiguous page runs from the buddy allocator, carved into equal-sized object slots. A slab tracks which slots are free via a bitmap or freelist. When you call kmem_cache_alloc(task_struct_cachep), the allocator pops a free slot off the current slab in O(1).

The three big wins:

Modern Linux ships SLUB (the default since 2.6.23), a simpler redesign. SLUB stores freelist pointers inside the free objects themselves (no separate metadata), and gives each CPU its own active slab — so the fast path is a lockless pointer bump. Contention only happens when a CPU's slab empties and it grabs a new one from the per-node partial list.

Real-world example: a busy web server doing 100k connections/sec creates and destroys sk_buff structures constantly. Check /proc/slabinfo:

skbuff_head_cache  48213  48384  256  16  1 : tunables ...

That's 48,213 active objects in 3,024 slabs (48384/16), each slab one page holding 16 objects of 256 bytes. Total overhead: ~12MB for 48k packet headers, with zero fragmentation. A naive kmalloc(256) from a 4KB-page allocator would either waste 15× the memory or recreate exactly this scheme.

Rule of thumb: objects per slab = PAGE_SIZE × order / object_size. SLUB picks the smallest order where waste is under ~1/16th. A 192-byte object lands in order-0 (4KB) slabs holding 21 objects with 64 bytes waste (1.5%). A 1500-byte object would waste 1096 bytes per page (27%), so SLUB picks order-1 (8KB) holding 5 objects with 692 bytes waste (8.4%).

You can watch this live: slabtop orders caches by memory usage. On any production box, dentry and inode_cache dominate — often hundreds of MB.

Key Takeaway: The slab allocator pools same-sized objects in pre-carved page runs so the kernel allocates million-object workloads in O(1) with near-zero fragmentation — and SLUB's per-CPU active slab makes the fast path lockless.

All newsletters