Linux page cache & dirty memory tuning
The Linux Page Cache transparently caches file data in unallocated physical RAM to accelerate read operations and buffer writes. However, default kernel settings designed for desktop systems can cause devastating multisecond I/O freezes on high-RAM database servers when gigabytes of unwritten ("dirty") pages are flushed to disk simultaneously.
Page lifecycle & kernel writeback mechanics
When an application calls write() without O_DIRECT or O_SYNC:
- The kernel allocates page frames in RAM, copies the user payload, marks the pages as Dirty, and returns immediately (sub-microsecond latency).
- As dirty pages accumulate, kernel background writeback flusher threads (
kworker/wb-*) awaken and stream data to the storage controller asynchronously. - If write throughput exceeds physical disk write speed and dirty pages hit the hard ceiling, the kernel suspends user processes and forces them to perform synchronous writeback.
Core page cache sysctl parameters
| Sysctl Parameter | Default | Architectural Role |
|---|---|---|
vm.dirty_background_ratio | 10% | Percentage of available memory where background asynchronous flushing begins. |
vm.dirty_background_bytes | 0 (Disabled) | Explicit byte threshold for background flushing (takes precedence over ratio). |
vm.dirty_ratio | 20% | Percentage of memory where applications are blocked and forced to flush synchronously. |
vm.dirty_bytes | 0 (Disabled) | Explicit byte threshold for synchronous application blocking (takes precedence over ratio). |
vm.dirty_expire_centisecs | 3000 (30s) | Maximum age (in 1/100ths of a second) a page can remain dirty before being forced to disk. |
vm.dirty_writeback_centisecs | 500 (5s) | Wakeup frequency interval for kernel background flusher threads. |
vm.vfs_cache_pressure | 100 | Tendency of kernel to reclaim directory and inode VFS metadata slabs vs page cache. |
Production tuning profiles
1. Enterprise Database Profile (PostgreSQL, MySQL, Redis, ScyllaDB)
For high-RAM database servers (32 GB to 1 TB+ RAM), prevent latency spikes by capping dirty memory to small, continuous byte flushes:
# /etc/sysctl.d/99-database-storage.conf
# Start flushing dirty pages immediately once 128 MB is dirty
vm.dirty_background_bytes = 134217728
# Block writers if dirty memory exceeds 512 MB (eliminates multi-gigabyte flush freezes)
vm.dirty_bytes = 536870912
# Wake flusher threads every 1 second (100 centiseconds)
vm.dirty_writeback_centisecs = 100
# Expire dirty pages after 10 seconds (1000 centiseconds)
vm.dirty_expire_centisecs = 1000
# Favor keeping inode and dentry trees in RAM
vm.vfs_cache_pressure = 50
# Conservative swappiness for predictable memory residency
vm.swappiness = 102. High-Throughput Bulk Data Ingestion / Logging Node
For logging ingestion clusters (Kafka, ClickHouse, Elasticsearch) where sequential write throughput is paramount and NVMe bandwidth is high:
# /etc/sysctl.d/99-streaming-ingest.conf
# Buffer larger batches in RAM before flushing
vm.dirty_background_bytes = 536870912 # 512 MB
vm.dirty_bytes = 2147483648 # 2 GB
vm.dirty_writeback_centisecs = 200 # 2 seconds
vm.dirty_expire_centisecs = 1500 # 15 seconds
vm.vfs_cache_pressure = 100Real-time monitoring & verification
Monitor real-time dirty page generation
# Inspect current dirty and writeback memory buffers in KB
watch -n 1 'grep -E "Dirty|Writeback" /proc/meminfo'
# Check active flusher threads
ps aux | grep "[k]worker.*wb"Reload sysctl configuration
# Apply all sysctl.d profiles immediately without reboot
sudo sysctl --systemComplementary storage optimizations
Page cache writeback tuning operates in concert with other kernel layers:
- Block I/O Scheduling: Pair writeback limits with the appropriate blk-mq I/O scheduler to prevent hardware dispatch starvation.
- Asynchronous I/O: High-throughput databases bypass the page cache entirely using
O_DIRECTalongside io_uring asynchronous ring buffers. - Filesystem Optimization: Tune journal commit timers and allocation sizing on Ext4 (
commit=30) and XFS (logbufs=8). - Verification: Validate write latency under load using the fio Storage Benchmarking Guide.
Frequently asked questions
What is the difference between vm.dirty_background_ratio and vm.dirty_ratio?
vm.dirty_background_ratio defines the threshold of dirty memory at which kernel background flusher threads (wb-*) asynchronously start writing dirty pages to disk while applications continue executing unblocked. vm.dirty_ratio is the hard ceiling: if dirty memory exceeds this limit, application write threads are forcefully throttled and blocked from generating new writes until pages are committed to storage.
Why should systems with large RAM use dirty_bytes instead of dirty_ratio?
On a modern server with 512 GB of RAM, a default vm.dirty_ratio=20 allows up to 102 GB of unwritten dirty pages to accumulate in RAM. When a flush occurs (or during an fsync()), the kernel attempts to flush gigabytes of data at once, causing severe latency spikes (I/O stalling) for 10 to 30+ seconds. Setting vm.dirty_background_bytes=256MB and vm.dirty_bytes=1GB caps flushes to manageable sizes.
What does vm.vfs_cache_pressure do?
vm.vfs_cache_pressure (default 100) controls the kernel's aggressiveness in reclaiming cached VFS directory entries (dentries) and inode objects relative to page cache data. A lower value (e.g. 50) tells the kernel to retain directory and inode trees in RAM longer, accelerating search and path traversal workloads.
What is O_DIRECT and how does it interact with the page cache?
Opening a file with the O_DIRECT flag (used by databases like Oracle, PostgreSQL, and ScyllaDB) instructs the kernel to completely bypass the OS page cache. I/O transfers occur directly between the application user-space memory buffer and the storage device controller, avoiding double-buffering in RAM.
Is echo 3 > /proc/sys/vm/drop_caches safe to run in production?
While non-destructive (it only drops clean cached pages and reclaimable slab objects), dropping caches in production wipes hot filesystem trees and database blocks from RAM, causing massive latency spikes as subsequent reads are forced to hit physical disks.