The Memory Compaction Daemon (kcompactd): How the Kernel Defragments Physical RAM Without Stopping Your Code

2026-06-19

You allocate a 2MB huge page. The buddy allocator needs 512 physically contiguous 4KB pages aligned on a 2MB boundary. After hours of uptime, your free memory is shredded — plenty of free pages, but scattered. kcompactd is the kernel thread that quietly walks memory zones and moves pages around to manufacture contiguous regions.

How it works. Compaction runs two cursors against each other inside a memory zone:

Pages get migrated by atomically updating every PTE that maps them, copying contents, and freeing the old page. Pinned pages (DMA buffers, mlocked memory, kernel slab pages) are unmovable and act as compaction roadblocks — one unmovable page in the middle of a 2MB region kills that huge page candidate forever.

Triggers. kcompactd wakes on three signals: (1) khugepaged needs a 2MB region to promote, (2) a high-order allocation just failed and woke the per-node kcompactd thread, (3) /proc/sys/vm/compaction_proactiveness (default 20) tells it to run periodically even without pressure.

Real-world example. A Redis instance on a 256GB box runs for a month with THP enabled. grep HugePages /proc/meminfo shows AnonHugePages: 8GB when it should be 200GB. /proc/vmstat reveals compact_fail: 4M, compact_stall: 12M — kcompactd is trying constantly and failing. The fix: echo 1 > /proc/sys/vm/compact_memory forces a synchronous full compaction, which freezes allocations for ~3 seconds but reclaims 180GB of huge-page-able memory. Long-term fix: reduce slab pressure (those kernel objects pin pageblocks as unmovable).

Rule of thumb. Cost of compacting one 2MB region ≈ copy 2MB + ~512 TLB shootdowns. On a 100GB/s memory subsystem with 1µs IPI cost per shootdown, that's ~20µs of copy + ~500µs of cross-core stalls. The shootdowns dominate. If you see compact_stall climbing faster than 1000/sec in vmstat, your workload is paying real latency for THP.

Check /proc/pagetypeinfo to see fragmentation directly: it shows free blocks per order per migratetype. Lots of Order-0 free, zero Order-9 free in the Movable type = classic fragmentation, compaction is your only escape.

Key Takeaway: kcompactd manufactures contiguous physical memory by migrating movable pages toward one end of a zone — but a single unmovable kernel allocation can permanently veto a 2MB huge page region.

All newsletters