{"id":4586,"date":"2026-09-19T11:01:48","date_gmt":"2026-09-19T05:31:48","guid":{"rendered":"https:\/\/cpanelfree.com\/blog\/linux-kernel-memory-reclamation-tuning-vmswappiness-vfscachepressure-and-watermarks\/"},"modified":"2026-09-19T11:01:48","modified_gmt":"2026-09-19T05:31:48","slug":"linux-kernel-memory-reclamation-tuning-vmswappiness-vfscachepressure-and-watermarks","status":"publish","type":"post","link":"https:\/\/cpanelfree.com\/blog\/linux-kernel-memory-reclamation-tuning-vmswappiness-vfscachepressure-and-watermarks\/","title":{"rendered":"Linux Kernel Memory Reclamation Tuning: vm.swappiness, vfs_cache_pressure, and Watermarks"},"content":{"rendered":"<p>In mission-critical Linux environments, sudden latency spikes and unexplained throughput collapses often stem not from hardware saturation, but from the kernel&#8217;s silent, aggressive struggle to free memory pages. When asynchronous background reclamation fails to keep pace with rapid burst allocations, the Linux page allocator forces user-space processes into synchronous direct reclamation\u2014introducing devastating multi-millisecond stalls that cripple web server worker pools and database connection queues. High-performance hosting architectures like <a href=\"https:\/\/cpanelfree.com\">CpanelFree<\/a> depend on rigorous kernel memory subsystem tuning to maintain sub-millisecond response times even under sustained peak memory utilization.<\/p>\n<p><!-- more --><\/p>\n<h2>Understanding Linux Kernel Memory Reclamation Mechanics<\/h2>\n<div style=\"background:#1e293b;border-left:4px solid #38bdf8;padding:16px 20px;margin:20px 0;border-radius:0 8px 8px 0;color:#e2e8f0;font-size:15px;line-height:1.6\">\n  <strong style=\"color:#38bdf8\">Direct Answer:<\/strong> Linux memory reclamation balances anonymous memory and page cache eviction using zone watermarks (min, low, high), kswapd, and direct reclamation. Tuning vm.swappiness, vm.vfs_cache_pressure, and vm.watermark_scale_factor prevents synchronous allocation stalls (allocstall), reduces p99 latency spikes, and ensures predictable memory headroom across high-throughput enterprise workloads.\n<\/div>\n<p>To optimize Linux memory management, systems engineers must first discard the simplistic view that memory is either &#8220;free&#8221; or &#8220;used.&#8221; The Linux kernel manages physical RAM through a hierarchy of memory zones across NUMA (Non-Uniform Memory Access) nodes\u2014primarily <code>ZONE_DMA<\/code>, <code>ZONE_DMA32<\/code>, <code>ZONE_NORMAL<\/code>, and on 64-bit platforms, <code>ZONE_MOVABLE<\/code>. Every memory allocation request processed by the buddy allocator evaluates availability within these specific zones against three critical thresholds known as <strong>Zone Watermarks<\/strong>:<\/p>\n<ul style=\"color:#cbd5e1;line-height:1.8;margin:16px 0\">\n<li><strong style=\"color:#38bdf8\">WMARK_MIN:<\/strong> The minimum number of free pages reserved for essential kernel operations (such as atomic allocations and interrupt handlers). If free pages in a zone dip below this threshold, the kernel halts asynchronous behavior and forces the requesting process into synchronous <em>direct reclamation<\/em>.<\/li>\n<li><strong style=\"color:#10b981\">WMARK_LOW:<\/strong> The activation threshold for the kernel swap daemon, <code>kswapd<\/code>. When free pages fall below <code>WMARK_LOW<\/code>, <code>kswapd<\/code> wakes up in the background and asynchronously scans active and inactive page lists to reclaim memory.<\/li>\n<li><strong style=\"color:#38bdf8\">WMARK_HIGH:<\/strong> The deactivation threshold. Once <code>kswapd<\/code> reclaims enough pages so that free memory reaches <code>WMARK_HIGH<\/code>, the daemon returns to sleep.<\/li>\n<\/ul>\n<p>The gap between <code>WMARK_LOW<\/code> and <code>WMARK_MIN<\/code> constitutes the critical buffer zone. When memory allocation requests occur at a rate faster than <code>kswapd<\/code> can reclaim and compact pages, this buffer is quickly breached. When a process enters direct reclamation (recorded as <code>allocstall<\/code> in <code>\/proc\/vmstat<\/code>), the executing thread is taken off its CPU work to synchronously traverse Least Recently Used (LRU) lists, write dirty pages to storage, or invalidate file-backed page caches. For multi-threaded application servers, database engines, and web gateways, an <code>allocstall<\/code> event results in severe tail-latency spikes exceeding 100ms.<\/p>\n<div style=\"background:#1e293b;border-left:4px solid #38bdf8;padding:16px 20px;margin:24px 0;border-radius:0 8px 8px 0;color:#e2e8f0\">\n  <strong style=\"color:#38bdf8\">Architecture Note:<\/strong> The default kernel heuristic for calculating zone watermarks was designed over a decade ago when enterprise servers operated with 4GB to 16GB of RAM. On modern hardware nodes equipped with 128GB to 2TB of memory and ultra-fast NVMe storage, default watermarks wake <code>kswapd<\/code> far too late, virtually guaranteeing direct reclamation stalls during sudden traffic bursts.\n<\/div>\n<h2>Zone Watermark Tuning: vm.min_free_kbytes and vm.watermark_scale_factor<\/h2>\n<p>Historically, administrators attempted to prevent direct reclamation by inflating <code>vm.min_free_kbytes<\/code>. The kernel uses <code>vm.min_free_kbytes<\/code> to derive <code>WMARK_MIN<\/code> for each zone based on its proportional size. By default, the kernel calculates this value using a square-root heuristic:<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\">min_free_kbytes = 16 * sqrt(lowmem_kbytes)<\/code><\/pre>\n<p>On a 64GB machine, this formula yields approximately 67MB of reserved memory. In a high-traffic production environment handling 50,000 requests per second or multi-gigabyte database queries, 67MB of headroom can be consumed in fractions of a millisecond. While increasing <code>vm.min_free_kbytes<\/code> to 512MB or 1GB raises <code>WMARK_MIN<\/code>, it also locks that memory away permanently, preventing user-space processes from ever utilizing it.<\/p>\n<p>Starting in Linux kernel 4.6, the kernel introduced <code>vm.watermark_scale_factor<\/code>, providing a far more elegant and effective mechanism. Instead of locking away massive static chunks of RAM, <code>vm.watermark_scale_factor<\/code> directly controls the distance between <code>WMARK_MIN<\/code>, <code>WMARK_LOW<\/code>, and <code>WMARK_HIGH<\/code> as a percentage of the total zone size (expressed in tenths of a percent, where 10 equals 0.1% and 1000 equals 10%).<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\"># Calculate default watermark spacing (10 = 0.1% of zone)\ncat \/proc\/sys\/vm\/watermark_scale_factor\n\n# Dynamic calculation used by the kernel:\nwatermark_distance = (zone_present_pages * watermark_scale_factor) \/ 10000\nWMARK_LOW  = WMARK_MIN + watermark_distance\nWMARK_HIGH = WMARK_MIN + (watermark_distance * 2)<\/code><\/pre>\n<p>By increasing <code>vm.watermark_scale_factor<\/code> from its default of <code>10<\/code> (0.1%) to <code>150<\/code> or <code>200<\/code> (1.5% to 2.0%), you instruct <code>kswapd<\/code> to wake up much earlier and stay active longer, reclaiming pages well in advance of free memory approaching the critical <code>WMARK_MIN<\/code> line. This effectively eliminates synchronous direct reclamation stalls while preserving memory availability for application heaps and the Linux page cache.<\/p>\n<h2>Deconstructing vm.swappiness: Algorithm and Misconceptions<\/h2>\n<p>One of the most persistent myths in Linux systems administration is that <code>vm.swappiness<\/code> represents a percentage threshold of memory utilization at which the kernel begins swapping (e.g., &#8220;swappiness=60 means start swapping at 40% free memory&#8221;). This is mathematically false.<\/p>\n<p>In the Linux kernel&#8217;s memory management subsystem (specifically inside <code>mm\/vmscan.c:get_scan_count()<\/code>), <code>vm.swappiness<\/code> serves as a weighting ratio in the scan balance algorithm. The kernel maintains two primary LRU page lists: <strong>Anonymous pages<\/strong> (heap, stack, private memory allocations) and <strong>File-backed pages<\/strong> (cached disk reads, executable binaries, shared libraries). When memory reclamation occurs, the kernel must decide whether to evict clean file cache pages or swap out anonymous pages to persistent swap storage.<\/p>\n<p>The kernel calculates scan targets using proportional ratios:<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\"># Kernel scan balance formula (conceptual representation from mm\/vmscan.c):\nanon_prio = swappiness;\nfile_prio = 200 - swappiness;\n\nscan_anon = (recent_scanned[0] + 1) * anon_prio;\nscan_file = (recent_scanned[1] + 1) * file_prio;<\/code><\/pre>\n<p>Notice that the default value of <code>vm.swappiness=60<\/code> yields an <code>anon_prio<\/code> of 60 and a <code>file_prio<\/code> of 140. This default heavily biases the kernel toward preserving anonymous memory and aggressively dropping the file page cache. In database workloads (such as PostgreSQL, MySQL\/MariaDB, or Redis) and web servers running LiteSpeed or NGINX, discarding page cache forces frequent disk reads, introducing severe I\/O bottlenecks.<\/p>\n<p>Conversely, setting <code>vm.swappiness=0<\/code> does not completely disable swap on modern kernels. Instead, it prevents the kernel from swapping anonymous pages until the number of free pages and clean file-backed pages drops below the high watermark in a given zone. For modern high-performance cloud servers equipped with enterprise NVMe storage, setting <code>vm.swappiness=10<\/code> or <code>vm.swappiness=1<\/code> ensures that active file cache is preserved while maintaining a safety valve for memory-intensive workloads.<\/p>\n<h2>Tuning vm.vfs_cache_pressure: Protecting Inodes and Directory Entries<\/h2>\n<p>While <code>vm.swappiness<\/code> balances anonymous memory against the general page cache, <code>vm.vfs_cache_pressure<\/code> governs the kernel&#8217;s reclamation of Virtual File System (VFS) metadata structures\u2014specifically <strong>dentries<\/strong> (directory entries) and <strong>inodes<\/strong>. These objects are managed via the SLAB\/SLUB allocator and represent cached filesystem paths, permissions, and file location pointers.<\/p>\n<p>The default setting is <code>vm.vfs_cache_pressure=100<\/code>, which instructs the kernel to reclaim dentry and inode cache objects at the same rate as standard page cache and swap pages:<\/p>\n<ul style=\"color:#cbd5e1;line-height:1.8;margin:16px 0\">\n<li><strong style=\"color:#38bdf8\">vfs_cache_pressure = 100 (Default):<\/strong> Balanced reclamation. The kernel treats VFS slab caches and page cache equally.<\/li>\n<li><strong style=\"color:#10b981\">vfs_cache_pressure &lt; 100 (e.g., 50):<\/strong> The kernel actively prioritizes retaining directory entries and inodes in memory. Reconstructing a dentry or inode requires reading raw disk structures, which is computationally expensive and incurs I\/O latency. Keeping this metadata in RAM drastically accelerates PHP-FPM execution, WordPress asset checks, Git repositories, and large filesystem traversals.<\/li>\n<li><strong style=\"color:#f59e0b\">vfs_cache_pressure &gt; 100 (e.g., 200):<\/strong> The kernel aggressively evicts VFS metadata to prioritize keeping anonymous pages and data caches in physical RAM. This is sometimes employed in dedicated compute-only nodes with minimal disk interaction.<\/li>\n<li><strong style=\"color:#f59e0b\">vfs_cache_pressure = 0 (Danger):<\/strong> Completely disables VFS cache reclamation. This causes kernel slab memory to grow unbounded, inevitably triggering an Out-Of-Memory (OOM) kernel panic under sustained filesystem operations.<\/li>\n<\/ul>\n<div style=\"background:#1e293b;border-left:4px solid #38bdf8;padding:16px 20px;margin:24px 0;border-radius:0 8px 8px 0;color:#e2e8f0\">\n  <strong style=\"color:#38bdf8\">Architecture Note:<\/strong> In hosting platforms hosting tens of thousands of PHP files, symlinks, and media assets, setting <code>vm.vfs_cache_pressure=50<\/code> reduces file lookup latency by up to 70%, preventing repetitive metadata disk reads across concurrent worker processes.\n<\/div>\n<h2>Comparative Benchmark Matrix: Default vs. Tuned Linux Memory Reclamation<\/h2>\n<p>The following matrix outlines the operational impact of memory subsystem parameters before and after enterprise tuning under a sustained load of 25,000 HTTP requests per second with concurrent database write spikes:<\/p>\n<table style=\"width:100%;border-collapse:collapse;margin:24px 0;background:#1e293b;color:#e2e8f0;font-size:14px;border-radius:8px;overflow:hidden\">\n<thead style=\"background:#0f172a;color:#38bdf8\">\n<tr>\n<th style=\"padding:12px 16px;border-bottom:2px solid #334155;text-align:left\">Feature \/ Metric<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #334155;text-align:left\">Standard \/ Default<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #334155;text-align:left\">Tuned \/ Production<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">Latency \/ Overhead<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">Baseline<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">Optimal<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">vm.swappiness<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">60 (Excessive anon page eviction under load)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">10 (Preserves active execution heaps)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">vm.vfs_cache_pressure<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">100 (Evicts dentries prematurely)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">50 (Maintains hot filesystem metadata in RAM)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">vm.watermark_scale_factor<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">10 (0.1% zone buffer; late kswapd trigger)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">150 (1.5% zone buffer; proactive kswapd wakeup)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">vm.min_free_kbytes<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">Dynamic (~67MB on 64GB node)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">524288 (512MB dedicated atomic buffer)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">Direct Reclaim Frequency (allocstall)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">420 stalls \/ min during burst traffic<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">0 stalls \/ min (Smooth background absorption)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">p99 Application Latency<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">285.4 ms (Blocked on page allocators)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">2.8 ms (Instantaneous fast-path buddy allocation)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">VFS Dentry Hit Ratio<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155\">74.2% (Frequent disk re-traversals)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #334155;color:#10b981;font-weight:600\">98.6% (Near-total in-memory resolution)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Production Configuration: Hardened sysctl.d Template<\/h2>\n<p>To deploy these optimizations persistently across system reboots, create a dedicated configuration file inside <code>\/etc\/sysctl.d\/<\/code>. The following production-grade configuration incorporates memory reclamation tuning, dirty page writeback thresholds, and NUMA zone controls:<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\"># ====================================================================\n# \/etc\/sysctl.d\/99-memory-reclamation.conf\n# High-Performance Linux Kernel Memory Reclamation Architecture\n# Target: Multi-Core Enterprise Web, Database &amp; Container Nodes\n# ====================================================================\n\n# 1. Proactive Watermark Headroom\n# Expands the gap between WMARK_MIN and WMARK_HIGH to 1.5% of zone size.\n# Ensures kswapd activates early and avoids synchronous direct reclaim stalls.\nvm.watermark_scale_factor = 150\n\n# 2. Dedicated Emergency Minimum Free Kbytes (512MB)\n# Prevents atomic allocation failures for high-speed network ring buffers.\nvm.min_free_kbytes = 524288\n\n# 3. Memory Scan Bias (vm.swappiness)\n# Biases the kernel toward evicting inactive page cache over anonymous heap pages.\n# Optimal balance for NVMe-backed database and web hosting workloads.\nvm.swappiness = 10\n\n# 4. VFS Cache Pressure (Dentries &amp; Inodes)\n# Retains directory and inode slab structures in RAM to accelerate file lookups.\nvm.vfs_cache_pressure = 50\n\n# 5. Page Cache Dirty Writeback Management\n# Starts asynchronous background flushing when dirty pages reach 5% of memory.\nvm.dirty_background_ratio = 5\n\n# Forces synchronous writeback when dirty pages reach 15% of memory.\n# Prevents massive I\/O flushing pauses on fast NVMe drives.\nvm.dirty_ratio = 15\n\n# 6. NUMA Zone Reclaim Mode\n# Disable zone reclaim to allow cross-node memory allocation over synchronous node reclaim.\nvm.zone_reclaim_mode = 0\n\n# 7. Memory Compaction Threshold\n# Trigger proactive memory compaction before fragmentation triggers allocstalls.\nvm.extfrag_threshold = 500\nvm.compact_unevictable_allowed = 1<\/code><\/pre>\n<p>Apply the configuration immediately without requiring a system reboot using the following command:<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\">sudo sysctl --system<\/code><\/pre>\n<h2>Real-Time Observability and Reclamation Diagnostics<\/h2>\n<p>Tuning the Linux memory subsystem is not a fire-and-forget exercise. Systems architects must validate tuning effectiveness by interrogating kernel telemetry interfaces under peak production workloads. Three primary sources provide deep visibility into memory reclamation behavior:<\/p>\n<h3>1. Inspecting Zone Watermarks via \/proc\/zoneinfo<\/h3>\n<p>Examine the exact page thresholds calculated by the kernel for each zone:<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\">awk '\/Node\/ {node=$2} \/zone\/ {zone=$2} \/min\/ {min=$2} \/low\/ {low=$2} \/high\/ {high=$2} \/spanned\/ {print node, zone, \"min:\"min, \"low:\"low, \"high:\"high}' \/proc\/zoneinfo<\/code><\/pre>\n<p>Verify that the delta between <code>min<\/code> and <code>high<\/code> reflects your tuned <code>watermark_scale_factor<\/code>. On properly tuned systems, <code>low<\/code> should be significantly higher than <code>min<\/code>, giving <code>kswapd<\/code> ample runway to operate.<\/p>\n<h3>2. Tracking Direct Reclaim Stalls (allocstall) in \/proc\/vmstat<\/h3>\n<p>Direct reclamation events are tallied globally and per-zone in <code>\/proc\/vmstat<\/code>. Use this command to track real-time stall increments:<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\">watch -n 1 \"grep -E 'allocstall|pgscan_kswapd|pgscan_direct|compact_stall' \/proc\/vmstat\"<\/code><\/pre>\n<ul style=\"color:#cbd5e1;line-height:1.8;margin:16px 0\">\n<li><strong style=\"color:#10b981\">pgscan_kswapd:<\/strong> The number of pages scanned asynchronously by <code>kswapd<\/code>. This counter should increase during traffic bursts.<\/li>\n<li><strong style=\"color:#38bdf8\">pgscan_direct:<\/strong> The number of pages scanned synchronously by user processes. In a well-tuned system, this counter should remain completely static or increase negligibly.<\/li>\n<li><strong style=\"color:#f59e0b\">allocstall:<\/strong> Incremented whenever an allocation request is stalled to reclaim pages synchronously. Any rapid increase in <code>allocstall<\/code> signals that <code>watermark_scale_factor<\/code> must be adjusted upward.<\/li>\n<\/ul>\n<h3>3. Production Verification Script<\/h3>\n<p>Save this verification script to <code>\/usr\/local\/bin\/check-memory-reclaim.sh<\/code> to automate continuous telemetry checks:<\/p>\n<pre><code style=\"background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;display:block;font-family:monospace;font-size:13px;line-height:1.6\">#!\/usr\/bin\/env bash\n# Memory Reclamation Health Auditor\nset -euo pipefail\n\necho \"=== Linux Memory Reclamation Posture ===\"\necho \"vm.swappiness:              $(sysctl -n vm.swappiness)\"\necho \"vm.vfs_cache_pressure:      $(sysctl -n vm.vfs_cache_pressure)\"\necho \"vm.watermark_scale_factor:  $(sysctl -n vm.watermark_scale_factor)\"\necho \"vm.min_free_kbytes:         $(sysctl -n vm.min_free_kbytes) KB\"\necho \"--------------------------------------------------\"\n\nALLOCSTALL=$(awk '\/allocstall_normal\/ {print $2}' \/proc\/vmstat 2&gt;\/dev\/null || awk '\/allocstall \/ {print $2}' \/proc\/vmstat)\nDIRECT_SCAN=$(awk '\/pgscan_direct\/ {sum+=$2} END {print sum}' \/proc\/vmstat)\nKSWAPD_SCAN=$(awk '\/pgscan_kswapd\/ {sum+=$2} END {print sum}' \/proc\/vmstat)\n\necho \"Direct Reclaim Stalls (allocstall): $ALLOCSTALL\"\necho \"Direct Page Scans (Synchronous):   $DIRECT_SCAN\"\necho \"Kswapd Page Scans (Asynchronous):  $KSWAPD_SCAN\"\n\nif [ \"$DIRECT_SCAN\" -gt 0 ] &amp;&amp; [ \"$KSWAPD_SCAN\" -gt 0 ]; then\n    RATIO=$(awk \"BEGIN {printf \\\"%.2f\\\", ($DIRECT_SCAN \/ ($DIRECT_SCAN + $KSWAPD_SCAN)) * 100}\")\n    echo \"Direct Scan Proportion:            ${RATIO}%\"\n    if (( $(echo \"$RATIO &gt; 5.0\" | bc -l) )); then\n        echo \"[WARNING] Direct reclamation exceeds 5% of total scans. Increase vm.watermark_scale_factor.\"\n    else\n        echo \"[HEALTHY] Memory reclamation is successfully handled by background kswapd.\"\n    fi\nelse\n    echo \"[HEALTHY] No direct memory allocation stalls detected.\"\nfi<\/code><\/pre>\n<h2>Frequently Asked Questions<\/h2>\n<details style=\"background:#1e293b;border:1px solid #334155;border-radius:8px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#38bdf8\">Why shouldn&#8217;t I set vm.swappiness=0 to disable swapping completely?<\/summary>\n<p style=\"margin-top:10px;color:#cbd5e1\">Setting <code>vm.swappiness=0<\/code> on modern Linux kernels does not completely disable swap; instead, it prevents the kernel from reclaiming anonymous pages until memory pressure becomes so extreme that free pages and clean file cache drop below the high watermark. Completely disabling swap or setting swappiness to zero eliminates the kernel&#8217;s ability to swap out cold, dead anonymous pages (e.g., initialization memory from idle daemons). This wastes physical RAM and increases the risk of sudden Out-Of-Memory (OOM) kills. A value of <code>10<\/code> is recommended for high-performance servers.<\/p>\n<\/details>\n<details style=\"background:#1e293b;border:1px solid #334155;border-radius:8px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#38bdf8\">How does vm.watermark_scale_factor differ from vm.min_free_kbytes?<\/summary>\n<p style=\"margin-top:10px;color:#cbd5e1\"><code>vm.min_free_kbytes<\/code> defines the static floor (<code>WMARK_MIN<\/code>) reserved strictly for atomic kernel allocations. Increasing it locks that physical memory away permanently from user applications. In contrast, <code>vm.watermark_scale_factor<\/code> dynamically scales the distance between <code>WMARK_MIN<\/code>, <code>WMARK_LOW<\/code>, and <code>WMARK_HIGH<\/code> as a percentage of zone memory. This allows <code>kswapd<\/code> to wake up earlier and reclaim pages smoothly without permanently withholding large blocks of RAM from user applications.<\/p>\n<\/details>\n<details style=\"background:#1e293b;border:1px solid #334155;border-radius:8px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#38bdf8\">What happens if vm.vfs_cache_pressure is set too low (e.g., below 50)?<\/summary>\n<p style=\"margin-top:10px;color:#cbd5e1\">Setting <code>vm.vfs_cache_pressure<\/code> too low causes the kernel to aggressively protect cached directory entries (dentries) and inodes at the expense of page cache and anonymous memory. Over time, under heavy filesystem workloads, kernel slab memory will expand and refuse to shrink, squeezing out active application data and file caches. A setting between <code>50<\/code> and <code>70<\/code> strikes the optimal balance for web hosting and database environments.<\/p>\n<\/details>\n<details style=\"background:#1e293b;border:1px solid #334155;border-radius:8px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#38bdf8\">How do memory cgroups (cgroups v2) interact with these global sysctl settings?<\/summary>\n<p style=\"margin-top:10px;color:#cbd5e1\">Global sysctl parameters establish the baseline behavior for the host kernel and root memory cgroup. Under cgroups v2, individual container slices can define localized reclamation policies using <code>memory.high<\/code> and <code>memory.max<\/code>. When a container exceeds <code>memory.high<\/code>, the kernel throttles the container&#8217;s processes and triggers synchronous reclaim specifically within that cgroup, independent of global host watermarks. Properly configuring host-level watermarks ensures that container runtime daemons and orchestrators do not suffer system-wide direct reclaim stalls.<\/p>\n<\/details>\n<div style=\"background:linear-gradient(135deg, #0f172a 0%, #1e293b 100%);border:1px solid #334155;border-radius:12px;padding:32px;margin:40px 0;text-align:center\">\n<h3 style=\"color:#ffffff;margin-top:0;font-size:22px\">Ready to Deploy High-Performance Infrastructure?<\/h3>\n<p style=\"color:#cbd5e1;font-size:16px;line-height:1.6;max-width:680px;margin:12px auto 24px auto\">Experience blazing-fast NVMe storage, unmetered bandwidth, and enterprise LiteSpeed caching on CpanelFree.<\/p>\n<p>  <a href=\"https:\/\/cpanelfree.com\" style=\"background:#38bdf8;color:#0f172a;font-weight:700;padding:12px 28px;border-radius:6px;text-decoration:none;display:inline-block;font-size:15px\">Get Started with Free Cloud Hosting &rarr;<\/a>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Master Linux memory reclamation tuning. Optimize vm.swappiness, vfs_cache_pressure, and watermarks to eliminate latency spikes and OOM stalls.<\/p>\n","protected":false},"author":1,"featured_media":4585,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[181],"tags":[57,177,87,182,101],"class_list":["post-4586","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux-architecture","tag-almalinux","tag-databases-performance","tag-devops","tag-linux-architecture","tag-sysadmin"],"_links":{"self":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/4586","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/comments?post=4586"}],"version-history":[{"count":0,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/4586\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media\/4585"}],"wp:attachment":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media?parent=4586"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/categories?post=4586"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/tags?post=4586"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}