Introduction
Memory management is at the heart of every Linux system’s performance and reliability. Whether you’re managing embedded devices, high-availability enterprise systems, containerized workloads, or high-performance computing clusters, a deep understanding of how Linux handles memory is critical. Unfortunately, Linux memory can appear cryptic at first glance: the fields in /proc/meminfo deviate from intuitive understanding, swap behavior mystifies many professionals, and out-of-memory (OOM) situations wreak havoc on production systems if left unchecked.
This post provides a comprehensive and tactical guide to mastering Linux memory management. We’ll dissect /proc/meminfo in detail, explore the mechanics of swap and swappiness, dive into how Linux selects processes for killing under memory pressure, and present specific approaches to optimize memory usage for performance-sensitive and mission-critical deployments.
Dissecting /proc/meminfo: What It Really Tells You
The /proc/meminfo virtual file provides a goldmine of real-time memory statistics. While common tools like free, vmstat, and top use this data, understanding the raw values gives you more insight into system behavior and anomalies.
Here’s a sample snippet from /proc/meminfo:
MemTotal: 16390348 kB
MemFree: 1284720 kB
MemAvailable: 8234560 kB
Buffers: 192640 kB
Cached: 3152948 kB
SwapCached: 0 kB
Active: 6823944 kB
Inactive: 3102952 kB
SwapTotal: 2097148 kB
SwapFree: 2097148 kB
Dirty: 112 kB
Writeback: 0 kB
Key definitions:
- MemTotal: Total usable RAM recognized by the kernel.
- MemFree: Physical RAM not currently used.
- MemAvailable: Estimated memory available for starting new applications without swapping.
- Buffers/Cached: Memory used by kernel buffers and file caches - often reclaimable.
- SwapTotal/SwapFree: Total size and free space of swap memory.
Important: Don’t mistake MemFree as the actual available memory - MemAvailable is the better gauge.
Interpreting Memory Pressure
To accurately determine if your system is under memory pressure:
- Monitor MemAvailable - not just MemFree
- If
MemAvailableis low andSwapFreestarts dipping, the system is starting to page out - If
CachedandInactiveremain high under stress, memory reclaim is being deferred
Tune with:
sysctl -w vm.vfs_cache_pressure=75
This adjusts how aggressively the system reclaims cache memory to free RAM.
Swap Configuration: Beyond Defaults
Swap acts as an overflow area for RAM - disk-based, and therefore slower. But using swap smartly enhances stability under pressure.
Optimal Swap Size
General guidance:
- <8GB RAM: Swap = 1.5–2x RAM
- 8–16GB RAM: ~1x RAM
- >16GB RAM: 4–8GB typically sufficient (or use ZRAM)
Use free -h to check if swap is active.
Tuning Swappiness: Prioritize RAM or Swap?
vm.swappiness defines how eagerly Linux pages memory to swap:
cat /proc/sys/vm/swappiness # check current value
sysctl -w vm.swappiness=10 # set new value
echo "vm.swappiness=10" >> /etc/sysctl.conf
0: Avoid swap unless absolutely necessary10: Good for low-latency workloads (databases, web servers)60(default): Balanced100: Swap aggressively - use sparingly
Swap Types: Best Options for Your Use Case
| Type | Use Case | Pros | Cons |
|---|---|---|---|
| Swap File | Flexible systems, VMs | Easy to resize | Slightly slower than partition |
| Swap Partition | Static servers, performance-critical | Fast access | Hard to resize |
| ZRAM | Embedded & low-RAM servers | In-RAM compression = fast swap | Uses RAM capacity |
Setting Up Swap
# Create and enable a 4G swap file
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Persist in fstab
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Verify with:
swapon --show
free -m
Understanding & Troubleshooting the OOM Killer
When Linux runs critically low on memory, it invokes the Out-of-Memory (OOM) Killer to free up RAM by terminating processes. Understanding and configuring this behavior can prevent catastrophic service downtime.
How the OOM Killer Works
Each process is assigned an oom_score, calculating its likelihood of being killed under memory pressure. Influencing factors:
- Memory usage
- Whether the process is a child or forked
oom_score_adj(-1000 to +1000) modifies protection level
Inspect scores with:
cat /proc/<pid>/oom_score
cat /proc/<pid>/oom_score_adj
Increase survival priority for essential processes:
echo -1000 > /proc/<pid>/oom_score_adj
Linux logs OOM events to dmesg:
dmesg | grep -i 'oom'
Real-World Scenario: Java Process Killed
If your application like Tomcat or Kafka suddenly dies:
- Check memory limits
- Look for
Killed process ... javain logs - Tune heap size using
-Xmxand reduce resident usage
Preventing OOM Conditions Proactively
Apply Cgroups via systemd or Kubernetes
Limit memory usage per service:
# systemd
systemctl set-property myapp.service MemoryMax=512M
Kubernetes example:
resources:
limits:
memory: "1Gi"
requests:
memory: "512Mi"
User-Level Constraints
Use /etc/security/limits.conf to apply per-user memory caps:
# Limit address space to 2GB
username hard as 2097152
Adjust Memory Overcommit Control
sysctl -w vm.overcommit_memory=2
sysctl -w vm.overcommit_ratio=50
0: Heuristic overcommit1: Always overcommit2: Cap toswap + RAM * overcommit_ratio
Use EarlyOOM or systemd-oomd
For desktops or Kubernetes nodes, these services act proactively on memory pressure.
Install EarlyOOM:
sudo apt install earlyoom
Monitor kill priority and act before the system freezes.
Optimizing Applications for Memory Usage
JVM Tuning
Avoid large default heap sizes:
-Xmx1024m -Xms512m
Use G1GC or Shenandoah collectors for memory-sensitive apps.
MySQL/PostgreSQL
Limit buffer sizes:
SET GLOBAL innodb_buffer_pool_size = 2G;
For PostgreSQL:
shared_buffers = 1GB
work_mem = 16MB
Caching Layers (Redis, Memcached)
Configure hard max memory and eviction policy:
maxmemory 512mb
maxmemory-policy allkeys-lru
Analyze Your App’s Memory Usage
Tools:
smem: Accurate RSS/PSS trackingpmap -x <pid>: Per-process memory mapvalgrind: Leak detection for custom appsps_mem.py: Human-readable memory report
Advanced Tips and Best Practices
Common Mistakes
- Interpreting
freewithout understanding cache/buffers - Disabling swap entirely in high-load environments
- Forgetting to set
oom_score_adjfor core services - Overcommitting memory without restraint (type 1 setting)
- Ignoring file-backed page cache buildup
Troubleshooting: Common Issues & Solutions
| Symptom | Cause | Fix |
|---|---|---|
| OOM kills during builds | High parallelism/low RAM | Limit threads, increase swap |
| Swap fills despite RAM available | High swappiness | Reduce vm.swappiness |
| Important daemon terminated | No oom protection | Set oom_score_adj low |
| System freezes | Overcommit + exhausted swap | Set overcommit_memory=2, tune swap |
| Apps killed after deployment | High RSS from warm caches | Pre-tune limits, stagger startup |
Best Practices Checklist
| Task | Recommendation |
|---|---|
| Swap Usage | Use swap; avoid disabling without testing |
| Application Limits | Apply memory caps via cgroups or limits.conf |
| OOM Protection | Adjust oom_score_adj for key services |
| Monitor Regularly | Use vmstat, smem, Prometheus, logs |
| Configure Alerts | Set thresholds on MemAvailable and swap use |
| Test for OOM Scenarios | Use stress-ng or similar to force trials |
| Profile Applications | With valgrind, smem, perf, top |
Resources & Next Steps
Key Docs:
Tools to Explore:
vmstat,smem,ps_mem,valgrind,heaptrack,perf- Visual dashboards: Netdata, Prometheus + Grafana
Next Actions:
- Audit current memory patterns on production nodes
- Enable and monitor swap intelligently
- Set up
oom_score_adjand cgroup limits for key apps - Use fault injection to simulate OOM conditions
- Regularly report memory and swap trends to improve forecasts
Conclusion
Mastering Linux memory is a vital step toward creating robust, performant infrastructure. From reading /proc/meminfo accurately to configuring swap for resilience and preventing OOM disasters, these fundamentals enable you to control system behavior during peak stress.
Key takeaways:
- Understand and use
/proc/meminfometrics, focusing on MemAvailable - Configure swap wisely - never disable without real justification
- Use
oom_score_adjand cgroup memory limits to protect key processes - Optimize app behavior: define memory bounds in app configs
- Test stress conditions before they happen in production
Control your memory landscape, reduce surprises, and build systems that thrive under pressure.
Happy coding!