Memory troubleshooting on Linux trips up a lot of people because the numbers don't mean what you expect. A server showing 95% memory used might be perfectly healthy, while one at 60% could be silently swapping. This guide covers the commands you actually need and explains what the output means.

The free command

free is the quick first check. Run it with -h for human-readable output:

free -h

Output looks like this:

               total        used        free      shared  buff/cache   available
Mem:            15Gi        4.2Gi       1.1Gi       312Mi       9.8Gi      10.8Gi
Swap:          2.0Gi          0B        2.0Gi
The column that matters is available, not free. The free column only shows truly unused RAM. The available column is an estimate of how much memory can be allocated without hitting swap — it accounts for reclaimable page cache and slab memory. Linux aggressively uses spare RAM as cache, which is a good thing.

In the example above, only 1.1 GiB is "free" but 10.8 GiB is available. The system is not under memory pressure.

When to worry

Start paying attention when the available column gets low (say, below 500 MB on a typical server) or when swap usage starts climbing. Swap usage of 0 is normal and ideal. Non-zero swap isn't always a crisis, but it means something has been pushed out of RAM — worth investigating.

# Watch memory every 2 seconds
watch -n 2 free -h

/proc/meminfo

For more detail than free provides, read /proc/meminfo directly:

cat /proc/meminfo

There are a lot of fields. The ones worth knowing:

FieldWhat it means
MemTotalTotal usable RAM (slightly less than physical RAM)
MemFreeRAM not being used at all — doesn't include reclaimable cache
MemAvailableEstimated RAM available for new allocations without swapping
BuffersRAM used for I/O buffers (reclaimable)
CachedPage cache — disk data in RAM (reclaimable)
SwapTotal / SwapFreeTotal swap space and unused portion
DirtyMemory waiting to be written to disk — high values can delay writes
SlabKernel slab allocator cache — can be large on busy systems

Filter to just the important fields:

grep -E 'MemTotal|MemFree|MemAvailable|Cached|Buffers|SwapTotal|SwapFree|Dirty' /proc/meminfo

vmstat for memory pressure

vmstat is useful for watching memory activity over time, particularly swap-in/swap-out rates:

# Report every 1 second, 10 samples
vmstat 1 10

Look at the si and so columns — swap-in and swap-out. Consistently non-zero values here indicate the system is actively swapping, which usually means you're short on RAM or something is leaking.

Per-process memory usage

To find which process is using the most memory:

# Sort by memory, show top 15
ps aux --sort=-%mem | head -15

# Resident set size for a specific PID
cat /proc/PID/status | grep -E 'VmRSS|VmSize|VmSwap'

VmRSS (Resident Set Size) is the actual physical RAM in use. VmSize is the virtual address space, which can look alarmingly large — JVMs and Go programs often show huge VmSize but modest VmRSS. Focus on VmRSS.

OOM killer events

If processes are being killed unexpectedly, the OOM (out-of-memory) killer may be the culprit:

# Check for OOM kills
dmesg | grep -i "oom\|killed process\|out of memory"

# Or via journal
journalctl -k | grep -i "oom\|killed process"

The output shows which process was killed and the memory state at the time. If this is happening regularly, you either need more RAM, better swap, or to find and fix the memory leak.

smem for shared memory accounting

smem is a third-party tool (install with apt install smem or yum install smem) that handles shared memory correctly. Standard tools can overcount memory when multiple processes share the same pages (like shared libraries).

# Top processes by PSS (proportional share)
smem -s pss -r | head -15

# System-wide summary
smem --system

PSS (Proportional Set Size) gives each process a fair share of any shared pages. It's the most accurate measure of how much RAM a process is really consuming.

Related guides