There are a lot of tools for looking at memory usage on Linux systems. Some are commonly used commands like ps, while others are tools like top that allow you to display system performance stats in various ways. In this post, we’ll look at a number of commands that can be very helpful in identifying the users and processes that are using the most memory.
Using free
One of the most obvious commands for viewing memory usage is the free command, which displays total, used and free memory. With the -h option, it displays the stats in “human-readable” format, displaying the numbers in megabytes, gigabytes, etc. as appropriate.
$ free
total used free shared buff/cache available
Mem: 3875540 2082216 109908 141692 1683416 1413648
Swap: 3874812 35328 3839484
$ free -h
total used free shared buff/cache available
Mem: 3.7Gi 2.0Gi 221Mi 132Mi 1.5Gi 1.4Gi
Swap: 3.7Gi 47Mi 3.6Gi
Using top
Another of the best commands for looking at memory usage is top. One extremely easy way to see what processes are using the most memory is to start top and then press shift+m to switch the order of the processes shown to rank them by the percentage of memory each is using. Once you’ve entered shift+m, your top output should reorder the task entries to look something like what you see below. Note the %MEM column, as shown below, displays processes in memory usage order.
top - 14:22:38 up 12 min, 3 users, load average: 0.02, 0.22, 0.32
MiB Mem : 3784.7 total, 967.8 free, 1249.0 used, 1567.9 buff/cache
MiB Swap: 3784.0 total, 3737.2 free, 46.8 used. 2170.7 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3953 fedora 20 0 1785992 537936 76568 S 0.0 13.9 0:37.63 gnome-software
3590 fedora 20 0 3868704 147920 96512 S 0.0 3.8 0:07.35 gnome-shell
5885 root 20 0 664948 131048 24632 S 0.0 3.4 0:07.94 packagekitd
5444 fedora 20 0 690380 77988 26884 S 0.0 2.0 0:02.11 python
The list will be limited by your window size, but the most significant processes with respect to memory usage will show up at the top of the process list.
If you want to focus on a single user, top can be used much in the same way that it is used above. Just add a username with the -U option as shown below and press the shift+m keys to order by memory usage:
$ top -U nemo
top - 14:28:54 up 18 min, 3 users, load average: 0.01, 0.08, 0.22
Tasks: 242 total, 1 running, 241 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.5 sy, 0.0 ni, 99.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3784.7 total, 761.7 free, 1118.5 used, 1904.5 buff/cache
MiB Swap: 3784.0 total, 3741.2 free, 42.8 used. 2298.2 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6906 nemo 20 0 225276 3712 2944 R 1.0 0.1 0:00.10 top
5681 nemo 20 0 30604 16004 10496 S 0.0 0.4 0:00.29 systemd
5702 nemo 20 0 168976 22256 2048 S 0.0 0.6 0:00.00 (sd-pam)
5718 nemo 20 0 17192 7224 5120 S 0.0 0.2 0:00.04 sshd
5732 nemo 20 0 224656 5248 3584 S 0.0 0.1 0:00.06 bash
Using htop
The htop command will run interactively – updating its display of all running processes, along with CPU, memory, and swap usage. You can also specify options when launching htop. For example, you can add a delay between its update using the -d option.
The htop output will look like what you see below. Notice the reports on the number of running tasks, load averages, overall memory usage and swap usage that precede details on tasks using the most memory.
0[ 2.69%] Tasks: 147, 345 thr, 100 kthr; 0 running
1[||| 5.2%] Load average: 0.05 0.06 0.03
Mem[||||||||||||||||1.16G/3.70G] Uptime: 81:51:21
Swp[||| 180M/3.70G]
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
1234 user 20 0 1234M 250M 15M R 14.5 13.5 1:34.56 /usr/bin/gno
5678 user 20 0 678M 100M 10M S 6.2 0.6 0:23.12 code
4321 root 20 0 512M 80M 5M S 3.1 0.5 0:12.45 systemd
8765 user 20 0 200M 50M 3M S 1.6 0.3 0:05.67 terminal
Using vmstat
The vmstat command provides information about processes, memory, paging, block IO, traps, disks and cpu activity. Here’s an example of its output:
$ vmstat
procs -----------memory--------- ---swap-- -----io--- -system- ------cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 185088 723712 2312 1998296 1 11 159 88 418 207 3 2 96 0 0
Note how the headings are used to separate the data into groups (e.g., memory includes swpd, fee, buff and cache). Here’s a listing of what each of these field headings means:
procs
- r: The number of processes waiting for run time
- b: The number of processes in uninterruptible sleep
memory
- swpd: the amount of virtual memory used
- free: the amount of idle memory
- buff: the amount of memory used as buffers
- cache: the amount of memory used as cache
- inact: the amount of inactive memory (-a option)
- active: the amount of active memory (-a option)
swap
- si: Amount of memory swapped in from disk (/s)
- so: Amount of memory swapped to disk (/s)
io
- bi: Blocks received from a block device (blocks/s)
- bo: Blocks sent to a block device (blocks/s)
system
- in: The number of interrupts per second, including the clock
- cs: The number of context switches per second
cpu (these are percentages of total CPU time)
- us: Time spent running non-kernel code (user time, including nice time)
- sy: Time spent running kernel code. (system time)
- id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time
- wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle
- st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown
Using ps
The ps command includes a column that displays memory usage for each process. To get the most useful display for viewing the top memory users, you can pass the ps output to the sort command. Here’s an example that provides a very useful display. The 4th field displays the percentage of memory used by each process.
$ ps aux | sort -rnk 4 | head -5
nemo 400 3.4 9.2 3309580 563336 ? Sl 08:59 1:36 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -prefsLen 9086 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 32469 8.2 7.7 3492840 469516 ? Sl 08:54 4:15 /usr/lib/firefox/firefox -new-window
nemo 32542 8.9 7.6 2875428 462720 ? Sl 08:55 4:36 /usr/lib/firefox/firefox -contentproc -childID 2 -isForBrowser -prefsLen 1 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 342 9.9 5.9 2854664 363528 ? Sl 08:59 4:44 /usr/lib/firefox/firefox -contentproc -childID 5 -isForBrowser -prefsLen 8763 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 2389 39.5 3.8 1774412 236116 pts/1 Sl+ 09:15 12:21 vlc videos/edge_computing.mp4
In the example above (truncated for this post), sort is being used with the -r (reverse), the -n (numeric) and the -k (key) options which are telling the command to sort the output in reverse numeric order based on the fourth column (memory usage) in the output from ps. If we first display the heading for the ps output, this is a little easier to see.
$ ps aux | head -1; ps aux | sort -rnk 4 | head -5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nemo 400 3.4 9.2 3309580 563336 ? Sl 08:59 1:36 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -prefsLen 9086 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 32469 8.2 7.7 3492840 469516 ? Sl 08:54 4:15 /usr/lib/firefox/firefox -new-window
nemo 32542 8.9 7.6 2875428 462720 ? Sl 08:55 4:36 /usr/lib/firefox/firefox -contentproc -childID 2 -isForBrowser -prefsLen 1 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 342 9.9 5.9 2854664 363528 ? Sl 08:59 4:44 /usr/lib/firefox/firefox -contentproc -childID 5 -isForBrowser -prefsLen 8763 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 2389 39.5 3.8 1774412 236116 pts/1 Sl+ 09:15 12:21 vlc videos/edge_computing.mp4
If you like this command, you can make it easier to use by setting up as an alias with a command like the one shown below. Don’t forget to add it to your ~/.bashrc file if you want to make it permanent.
$ alias mem-by-proc="ps aux | head -1; ps aux | sort -rnk 4"
You can also use a ps command to rank an individual user’s processes by memory usage. In this example, we do this by selecting a single user’s processes with a grep command:
$ ps aux | head -1; ps aux | grep ^nemo| sort -rnk 4 | more
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nemo 32469 7.1 11.5 3724364 701388 ? Sl 08:54 7:21 /usr/lib/firefox/firefox -new-window
nemo 400 2.0 8.9 3308556 543232 ? Sl 08:59 2:01 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -prefsLen 9086 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni/usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 32542 7.9 7.1 2903084 436196 ? Sl 08:55 8:07 /usr/lib/firefox/firefox -contentproc -childID 2 -isForBrowser -prefsLen 1 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 342 10.8 7.0 2941056 426484 ? Rl 08:59 10:45 /usr/lib/firefox/firefox -contentproc -childID 5 -isForBrowser -prefsLen 8763 -prefMapSize 210653 -parentBuildID 20200107212822 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 32469 true tab
nemo 2389 16.9 3.8 1762960 234644 pts/1 Sl+ 09:15 13:57 vlc videos/edge_computing.mp4
nemo 29527 3.9 3.7 2736924 227448 ? Ssl 08:50 4:11 /usr/bin/gnome-shell
Using ps along with other commands
Commands can get complicated when you want to compare users’ memory usages with each other. In that case, creating a by-user total and ranking them is a good technique, but it requires a little more work and requires a number of commands.
The script below counts up the memory usage for each active user (including system accounts). The first (outer) for loop creates a list of users with active processes. The second (inner) counts up the percentage of memory each of those users’ processes occupy.
#/bin/bash
echo -e USER "\t" % memory used
echo "=================="
for USER in `ps aux | grep -v USER | awk '{print $1}' | sort | uniq`
do
sum=0
for num in `ps aux | grep $USER | awk '{print $4}'`
do
sum=`echo $sum + $num | bc`
done
echo -e $sum "\t" $USER
done
Output from this script might look like this:
$ ./show_user_mem_usage
USER % memory used
==================
.1 avahi
.1 chrony
.3 colord
.9 dbus
44.0 fedora
.9 geoclue
1.0 pcp
.2 polkitd
16.2 root
0 rtkit
1.5 shs
.5 systemd+
Viewing the /proc/meminfo file
The /proc/meminfofile provides a memory usage report for all kinds of system resources. The example below should give you an idea how detailed this data can be. The column command allows you to view the long list of stats in a single window. It adjusts to the width of your screen.
$ cat /proc/meminfo | column
MemTotal: 3875540 kB SecPageTables: 0 kB
MemFree: 740468 kB NFS_Unstable: 0 kB
MemAvailable: 2341612 kB Bounce: 0 kB
Buffers: 2312 kB WritebackTmp: 0 kB
Cached: 1890228 kB CommitLimit: 5812580 kB
SwapCached: 292 kB Committed_AS: 5574984 kB
Active: 1295012 kB VmallocTotal: 34359738367 kB
Inactive: 1458080 kB VmallocUsed: 51380 kB
Active(anon): 617436 kB VmallocChunk: 0 kB
Inactive(anon): 331996 kB Percpu: 1832 kB
Active(file): 677576 kB HardwareCorrupted: 0 kB
Inactive(file): 1126084 kB AnonHugePages: 0 kB
Unevictable: 20512 kB ShmemHugePages: 0 kB
Mlocked: 5568 kB ShmemPmdMapped: 0 kB
SwapTotal: 3874812 kB FileHugePages: 0 kB
SwapFree: 3689724 kB FilePmdMapped: 0 kB
Zswap: 0 kB CmaTotal: 0 kB
Zswapped: 0 kB CmaFree: 0 kB
Dirty: 768 kB Unaccepted: 0 kB
Writeback: 0 kB HugePages_Total: 0
AnonPages: 880780 kB HugePages_Free: 0
Mapped: 313200 kB HugePages_Rsvd: 0
Shmem: 83768 kB HugePages_Surp: 0
KReclaimable: 93488 kB Hugepagesize: 2048 kB
Slab: 203160 kB Hugetlb: 0 kB
SReclaimable: 93488 kB DirectMap4k: 173804 kB
SUnreclaim: 109672 kB DirectMap2M: 3893248 kB
KernelStack: 9704 kB DirectMap1G: 0 kB
PageTables: 25668 kB
Using dstat
The dstat command provides real-time statistics on various system resources, including CPU, memory, disk, network and more. Here’s an example of the command’s output.
$ dstat
You did not select any stats, using -cdngy by default.
----total-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read writ| recv send| in out | int csw
0 0 99 0 0| 0 0 | 506B 658B| 0 0 | 91 172
0 0 99 0 0| 0 0 | 60B 338B| 0 0 | 90 152
3 1 96 0 0| 0 0 | 60B 354B| 0 0 | 277 518
0 0 99 0 0| 0 0 | 60B 354B| 0 0 | 106 135
1 0 99 0 0| 0 4096B| 60B 354B| 0 0 | 97 162
1 0 99 0 0| 0 0 |7523B 492B| 0 0 | 81 130
0 1 98 0 0| 0 0 | 506B 354B| 0 0 | 155 170
0 0 99 0 0| 0 0 | 120B 424B| 0 0 | 59 102 ^C
Wrap-up
There are certainly quite a few ways to display memory usage on Linux. To focus on how much memory various processes and users are consuming, get accustomed to the command options that are available to you. And, when it’s helpful, create aliases to make your queries easier.