Solving Linux Page Cache Thrashing & OOM in 24/7 Video Recording
One of the most elusive and catastrophic problems in 24/7 CCTV and NVR video recording on Linux is Page Cache Thrashing and Out-Of-Memory (OOM) Panics.
🔍 The Root Cause: Why Linux Memory Explodes During Video Recording
When an application records continuous video streams (e.g. 50+ RTSP cameras generating 500 MB/s of data) using standard file I/O (os.File.Write() in Go or write() in C), the Linux kernel does not write data directly to physical storage immediately.
Instead:
- Linux Caches Every Written Byte: The kernel places written video blocks into the Page Cache (RAM) marked as "dirty pages".
- Delayed Flushes: Background kernel flusher threads (
pdflush/kswapd) periodically flush dirty pages to NVMe/HDD disks. - Cache Eviction Crisis: With 50–100 cameras, the stream of incoming video data is relentless. The kernel prioritizes caching video pages until 90%+ of total physical RAM is consumed by the page cache.
- The OOM Spike: When a neighboring process (such as a database, WebRTC encoder, or Go runtime GC) urgently needs memory, Linux has to freeze file I/O to evict pages or panic and invoke the OOM Killer, crashing your video server.
🛑 Why Traditional Solutions Fail
O_DIRECT: Bypasses the cache entirely, but requires strict 4KB sector alignment in memory. Go's runtime allocator and GC cannot guarantee slice alignment without messyunsafepointer math, manual block allocations, and zero-padding uneven video frames.mmap: Requires continuousftruncateand memory remapping as live video files grow, causing heavy page fault overhead in Go.- Global
vm.dirty_ratio: Tweaking global/proc/sys/vm/dirty_ratiochanges cache eviction for the entire operating system, degrading performance for databases and system processes.
✅ The RUSEON Core Solution: POSIX_FADV_DONTNEED
In RUSEON Core, we solve this at the kernel syscall layer without unsafe or global OS hacks:
- Sequential Chunk Writes: Video is written in discrete Fragmented MP4 (
fMP4) segments using standardos.File. - Explicit Cache Eviction: Immediately after syncing a completed video chunk to disk, RUSEON invokes the
POSIX_FADV_DONTNEEDsystem call:
go
// Flush chunk to storage
chunkFile.Sync()
// Instruct Linux kernel to immediately drop video pages from RAM
syscall.Fadvise(int(chunkFile.Fd()), 0, int64(chunkSize), syscall.FADV_DONTNEED)📈 Results:
- Zero Page Cache Hoarding: RAM usage remains perfectly flat (~180MB) whether recording 1 hour or 365 days.
- Predictable I/O: Eliminates kernel freeze spikes and I/O wait stalls.
- No Root Permissions Needed: Works on standard Linux, Docker containers, and Kubernetes pods without special privileges.