Guides

How to check memory usage in Linux: free -h, /proc/meminfo, top and ps

Check memory usage on Linux with free -h and read the available column, not free. Plus /proc/meminfo, vmstat, top, ps by RSS, swap and OOM signs.

Published ~9 min read
On this page

Short answer: to check memory usage in Linux, run free -h. It prints total, used, free, buff/cache and available memory, plus swap. Read the available column: that is how much RAM programs can still get without swapping. A small “free” figure is normal, because Linux lends idle RAM to the disk cache and hands it back on demand.

the short version
free -h                          # the overview: read "available"
ps aux --sort=-%mem | head       # the processes using the most RAM
vmstat 1 5                       # five one-second samples: is it swapping right now?
swapon --show                    # is there any swap at all?
grep -E 'MemTotal|MemAvailable|SwapFree' /proc/meminfo   # the raw numbers

The commands and output layouts on this page were checked on Debian 12 (kernel 6.1, procps-ng 4.0.2, util-linux 2.38.1) in a KVM guest on 21 October 2026; the numbers in the example outputs are illustrative. The smem, dmidecode and out-of-memory parts follow their documentation and the kernel’s log format and were not run there. Ubuntu, Rocky Linux and AlmaLinux ship the same tools.

Cheat sheet: memory commands by question

QuestionCommand
How much RAM is there, and how much is left?free -h
Show buffers and cache separatelyfree -h -w
Refresh every 2 secondsfree -h -s 2
Every counter the kernel keepscat /proc/meminfo
Is the server swapping right now?vmstat 1
Which processes use the most RAM?ps aux --sort=-%mem | head
Live view sorted by memorytop -o %MEM
Memory of one processgrep -E 'VmRSS|VmHWM|VmSwap' /proc/PID/status
Fair share per process (PSS)sudo smem -r -s pss -k
Swap devices and their useswapon --show
Did the kernel kill something for memory?sudo journalctl -k | grep -i oom
How much RAM is installed?lsmem

How do I read free -h?

Example output · free -h on a 4 GB VPS (illustrative numbers)
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       1.1Gi       412Mi        21Mi       2.5Gi       2.7Gi
Swap:          2.0Gi          0B       2.0Gi
  • total: the RAM the kernel manages (MemTotal), slightly less than the RAM in the machine or the plan. More on that below.
  • used: memory that is in use and cannot simply be handed out. Since procps-ng 4.0.1 (Debian 12, Ubuntu 24.04) it is calculated as total minus available; older versions such as Ubuntu 22.04’s procps 3.3 subtract free, buffers and cache instead, so the same machine shows a slightly different “used” on the two.
  • free: RAM nobody uses for anything, not even cache. On a server that has been up for a while this is small, and that is good: unused RAM does no work.
  • shared: mostly tmpfs, such as /dev/shm and /run.
  • buff/cache: kernel buffers, the page cache (recently read files) and reclaimable kernel slab. Most of it is given back the moment a program asks for memory. free -h -w shows buffers and cache as two columns.
  • available: the kernel’s estimate (MemAvailable) of how much memory a new program can get without pushing anything to swap. This is the number to watch.

With the new calculation, free, used and buff/cache no longer add up to total. That is expected: available counts only the part of the cache the kernel can really reclaim, and used is derived from it. Units are binary: Gi is a gibibyte (1,024 MiB). free -m prints mebibytes without suffixes, which is handier in scripts, and --si switches to powers of 1,000.

Why is free memory so low?

Because Linux uses otherwise idle RAM as a file cache. Read a 2 GB log once and it stays in RAM until something needs the space, so reading it again is fast. The cache shrinks automatically under pressure, which is why a server with 400 MB “free” and 2.7 GB “available” is healthy. Dropping the cache by hand (as root, echo 3 > /proc/sys/vm/drop_caches) only makes the next reads slower; it is a benchmarking tool, not a fix.

What does /proc/meminfo show?

free, top and htop all read /proc/meminfo. Reading it directly gives you the counters they summarise, in kibibytes:

the lines worth knowing
grep -E '^(MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapTotal|SwapFree|Shmem|SReclaimable|AnonPages|Committed_AS|Dirty):' /proc/meminfo
FieldWhat it means
MemTotalUsable RAM the kernel manages
MemFreeCompletely unused RAM (free's "free")
MemAvailableEstimate of RAM available for new programs without swapping
BuffersKernel buffers for block devices
CachedPage cache, including tmpfs and shared memory
SReclaimableKernel slab memory that can be freed (free adds it to cache)
AnonPagesMemory of programs that is not backed by a file: heaps, stacks
Shmemtmpfs and shared memory segments
SwapTotal / SwapFreeSwap size and the part not in use
Committed_ASMemory all processes have asked for, used or not yet
DirtyChanged file data not yet written to disk

Committed_AS above MemTotal plus swap is not an error on its own: Linux overcommits by default, because programs reserve more than they ever touch. It becomes interesting when available is low at the same time.

Is the server swapping right now? vmstat 1

Example output · vmstat 1 5 (illustrative numbers)
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0  51200 421904  60212 2554180    0    0     3    18  210  395  4  1 95  0  0
 2  0  51200 420112  60212 2554200    0    0     0    44  480  820  6  2 92  0  0
 1  0  51200 419876  60220 2554204    0    0     0    12  455  790  5  1 94  0  0

The first line is an average since boot; the following lines are the live samples. Memory columns are in KiB (-S M switches to MiB). swpd is swap in use, and si and so are the memory swapped in and out per second. A few megabytes in swap with si and so at zero is harmless: idle pages were moved out once. Non-zero si and so in sample after sample means the server is short of RAM right now, and a high wa (waiting for I/O) usually comes with it. vmstat -s -S M prints a one-off list of the same totals.

For a measure that does not depend on swap at all, read the kernel’s pressure stall information. cat /proc/pressure/memory prints how much of the last 10, 60 and 300 seconds tasks spent waiting for memory; anything above zero in the avg10 field during normal operation is worth a look.

How do I sort processes by memory in top and htop?

  • top: press Shift+M while it runs, or start it with top -o %MEM. The two memory lines in the header are MiB Mem (total, free, used, buff/cache) and MiB Swap, which ends with avail Mem, the same estimate as free’s available.
  • htop: press M, or start it with htop -s PERCENT_MEM. The memory bar colours separate used memory from buffers and cache; htop explained decodes them and the RES, SHR and VIRT columns.

Which process is using the memory?

top memory users
ps aux --sort=-%mem | head                     # BSD-style list, biggest first
ps -eo pid,user,rss,comm --sort=-rss | head    # only the columns you need (RSS in KiB)
ps -C php-fpm8.2 -o rss= | awk '{s+=$1} END {print s/1024 " MiB"}'   # all workers of one program

In ps aux, %MEM is RSS as a share of physical RAM, RSS is the resident set in KiB and VSZ the virtual size. The ps aux guide covers every column. For a single process, its status file holds the peak as well as the current value:

one process, by PID
grep -E 'VmRSS|VmHWM|RssAnon|RssFile|VmSwap' /proc/1234/status
# VmRSS:    184320 kB   resident now
# VmHWM:    412516 kB   highest resident value since the process started
# RssAnon:  151200 kB   heap and stack
# RssFile:   33120 kB   mapped files such as libraries
# VmSwap:        0 kB   this process's pages in swap

VmHWM is the high-water mark: a worker that sits at 180 MB but peaked at 400 MB needs the 400 MB when you size the server or set pm.max_children in PHP-FPM.

RSS, PSS, USS and VSZ: which number is real?

MeasureWhat it countsUse it for
VSZ (VIRT)All address space the process has mapped, used or notAlmost nothing; it is routinely far above RAM
RSS (RES)Pages of the process in RAM, shared libraries counted in fullA quick ranking; sums over-count
PSSRSS with each shared page divided by the number of processes sharing itAdding up a group of processes honestly
USSPages only this process usesWhat you would get back by killing it

RSS counts shared pages in every process that maps them, so adding up the RSS of 20 PHP or Postgres workers can exceed the RAM in the machine. PSS splits each shared page between its users. The kernel publishes it per process in /proc/PID/smaps_rollup: for a short-lived head process in the test, it listed Rss: 1684 kB but Pss: 218 kB, because almost all of it was the shared C library. smem reads those files for every process:

smem (Debian, Ubuntu: apt install smem)
sudo smem -r -s pss -k | head -15    # processes by PSS, biggest first
sudo smem -u -k                      # totals per user
sudo smem -w -k                      # kernel, cache and processes for the whole system

How do I check swap usage?

swap
swapon --show                     # no output: no swap configured
free -h                           # the Swap: line
grep -s VmSwap /proc/[0-9]*/status | sort -k2 -n | tail   # which processes sit in swap

Many VPS images ship without swap, and then the Swap line reads 0B across the board. A small swap file gives the kernel somewhere to put idle pages instead of killing a process when memory runs out for a moment; adding swap space on Linux shows how to create one and how to set vm.swappiness. Swap is a cushion, not extra RAM: a server that swaps all day is too small for its job.

Signs that the server ran out of memory

  • A process dies with just Killed on the terminal, or a container exits with code 137.
  • The kernel log has a line like Out of memory: Killed process 2314 (mysqld) total-vm:… anon-rss:….
  • systemctl status of a service shows Result: oom-kill.
  • The server becomes sluggish, load climbs, and kswapd0 shows up near the top of top.
search the kernel log
sudo dmesg -T | grep -i -E 'out of memory|killed process'
sudo journalctl -k -b -1 | grep -i oom     # the previous boot, after a crash or reboot

The process named in that line is the one the kernel chose to kill, not necessarily the one that ate the memory. The out-of-memory killer guide walks through confirming the cause and keeping it from happening again. Memory pressure also shows up as CPU load, because reclaiming pages and swapping cost CPU time and I/O waits; if you came here from a busy CPU graph, check VPS high CPU usage as well.

Why does my VPS show less RAM than the plan?

MemTotal is the memory the kernel manages after it has set aside what it needs at boot: its own code, firmware reservations and the table that describes every page of RAM (64 bytes per 4 KiB page on x86-64, about 1.6 %). In the Debian 12 KVM guest used for this page, lsmem reported Total online memory: 40G while free -h showed a total of 39Gi, so about 850 MiB never appeared in MemTotal. On a 4 GB plan, expect a total of roughly 3.8Gi.

installed vs usable
lsmem | tail -3                    # memory the system has online, in blocks
grep MemTotal /proc/meminfo        # what the kernel can hand out
sudo dmidecode -t memory | grep -E 'Size|Type:|Speed'   # bare metal: the modules in the slots

Two more reasons for a gap: GB versus GiB (a “4 GB” figure in powers of 1,000 is only 3.7 GiB), and on bare metal, memory used by integrated graphics or firmware. Inside a virtual machine, dmidecode describes the hypervisor’s virtual hardware rather than real modules; the ECC memory guide explains what it can and cannot tell you there. If the total is far below what you pay for, not a few percent, ask the provider.

How do I know the server needs more RAM?

Look at the trend, not one snapshot. A server that keeps a healthy share of its RAM available at peak time, swaps nothing in vmstat and has no OOM lines in the kernel log has enough. Act when available falls close to zero at busy hours, si/so stay non-zero, or the OOM killer appears. First check whether one process grows without limit (a leak shows as an RSS that only ever rises) and whether caches such as a database buffer pool or pm.max_children are set larger than the machine. Capping a service with MemoryMax= in its systemd unit keeps one program from taking the rest of the server down with it.

Frequently asked

What is the difference between free and available memory in Linux?

free is RAM that nothing uses at all, not even the file cache. available is the kernel's estimate (MemAvailable in /proc/meminfo) of how much memory new programs can get without swapping, counting the cache it can reclaim. On a healthy server free is often small and available large, so watch available.

How do I see which process uses the most memory?

Run 'ps aux --sort=-%mem | head', or 'ps -eo pid,user,rss,comm --sort=-rss | head' for just the resident memory in KiB. In top press Shift+M, in htop press M. RSS counts shared libraries in every process that uses them, so for a fair total per program use PSS from smem or /proc/PID/smaps_rollup.

Why does my VPS show less RAM than my plan?

The kernel reserves memory at boot for its own code and firmware areas, and the table that describes every page of RAM alone takes about 1.6 % of it, so free -h on a 4 GB server shows a total of about 3.8Gi. GB versus GiB adds to the gap. A difference of a few percent is normal; a large one is a question for the provider.

How do I check swap usage in Linux?

swapon --show lists swap devices and files with their size and use; no output means there is no swap. The Swap line of free -h shows total and used, and vmstat 1 shows si and so, the memory swapped in and out per second. si and so that stay above zero mean the server is short of RAM.

Related articles

All guides