LINUXOR.SK ... open source notes ...

Memory 02 - Diagnosing process memory use in Linux

category: learnz/memory · date: 2017-01-01 · updated: 2017-01-14 · theme: github

Linux Process Memory Learning · Previous: The virtual memory of a user process in Linux

The Slovak original of this document: Memory 02 - Diagnostika využívania pamäte procesov v OS Linux (slovensky).

1 Tools for diagnosing memory use in Linux

ps displays information about a selection of the active processes. If you want a repetitive update of the selection and the displayed information, use top(1) instead.

The pmap command reports the memory map of a process or processes.

smem is a tool that can give numerous reports on memory usage on Linux systems. Unlike existing tools, smem can report proportional set size (PSS), which is a more meaningful representation of the amount of memory used by libraries and applications in a virtual memory system. Because large portions of physical memory are typically shared among multiple applications, the standard measure of memory usage known as resident set size (RSS) will significantly overestimate memory usage. PSS instead measures each application's "fair share" of each shared area to give a realistic measure.

github raw - ps_mem.py Try to determine how much RAM is currently being used per program. Note per _program_, not per process. So for example this script will report RAM used by all httpd process together. In detail it reports: sum(private RAM for program processes) + sum(Shared RAM for program processes). The shared RAM is problematic to calculate, and this script automatically selects the most accurate method available for your kernel.

2 Reading the memory figures the diagnostic tools report

A short introduction to reading the memory figures the diagnostic tools report:

The size of the whole virtual memory of the process, or of the address space available to it. In other words it is the total size of the virtual memory of the process regardless of whether its pages are loaded into physical memory or not. The problem with this figure is that it also includes memory that was allocated, for example with "malloc()", but nothing has been written to it yet. So this figure is not very suitable for determining the real memory use of a program.

How much memory the process is using right now. That is the size of the process memory currently held in RAM. In other words, it is the total number of memory pages of the process currently loaded into physical memory. The problem with this figure is that it also includes the memory used for the shared libraries the process uses. This means that if we have a shared library "lib" used by 2 programs ("proces1" and "proces2"), memory of size "V" is allocated for "lib", but only once. If we calculated the memory use of "proces1" and "proces2" by just adding up the RSS values, we would needlessly (and wrongly) count the shared memory twice. So this figure is not very suitable for determining the real memory use of a single program.

Much like RSS, except that the memory allocated for a shared library is divided by the number of processes using it. If a shared library "lib" takes 100 KB and two programs ("proces1" and "proces2") use it, PSS = 100/2 = 50 KB. So this figure is better than RSS, but it is also not very suitable for determining the real memory use of a single program. The best use of this figure is to add it up for all processes, which gives a good view of the current memory use of the whole system.

How much private memory the process is using right now. That is the memory that is unique to the process. So this figure is the most suitable for determining the real memory use of a single program.

The tools that report memory use give the same figures different column names. The following table summarises these differences.

asciiart
+--------------------+---------+-------------------+---------+-------------------------------+
| Program\Figure     | VSS     | RSS               | PSS     | USS                           |
+--------------------+---------+-------------------+---------+-------------------------------+
| ps                 | VSZ     | RSS               | -       | -                             |
+--------------------+---------+-------------------+---------+-------------------------------+
| pmap -x            | Kbytes  | RSS               | -       | -                             |
+--------------------+---------+-------------------+---------+-------------------------------+
| pmap -X            | Size    | RSS               | PSS     | -                             |
+--------------------+---------+-------------------+---------+-------------------------------+
| pmap -XX           | Size    | RSS               | PSS     | Private_Clean + Private_Dirty |
+--------------------+---------+-------------------+---------+-------------------------------+
| smem               | VSS     | RSS               | PSS     | USS                           |
+--------------------+---------+-------------------+---------+-------------------------------+
| ps_mem.py          | -       | Shared + Private  | Shared  | Private                       |
+--------------------+---------+-------------------+---------+-------------------------------+

Points [2.1] to [2.4] run "ps", "smem", "pmap" and "ps_mem.py" so that their output is as similar as possible.

2.1 Running "ps" and reading the memory figures for PID=100886

asciiart
# ps -eo pid,comm,vsz,rss -q 100886
----------------------------------------------------------------------------------------------------------------
PID    COMMAND            VSZ   RSS
100886 mc              163996  5364

2.2 Running "smem" and reading the memory figures for PID=100886

Note 1: I do not know why "smem" always puts a row for the "smem" process itself into the output. It is written in Python, so row 2 holds the memory figures for the Python interpreter.
Note 2: Given note 1, it might be worth writing my own tool.
asciiart
# ./smem -c 'pid name maps vss uss pss rss' -P /usr/bin/mc
----------------------------------------------------------------------------------------------------------------
PID    Name                      Maps      VSS      USS      PSS      RSS
100886 mc                         118   164000     2932     3213     5364
101585 python                      82   146072     4660     5342     6836

2.3 Running "pmap" and reading the memory figures for PID=100886

Note: the output is quite complex and long. For this reason only the first two and the last two rows are shown.
asciiart
# pmap -XX 100886 | head -n 2;  pmap -XX 100886 | tail -n 2;
----------------------------------------------------------------------------------------------------------------
100886:   /usr/bin/mc -P /tmp/mc-root/mc.pwd.100867
         Address Perm   Offset Device    Inode   Size  Rss  Pss Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous AnonHugePages Swap KernelPageSize MMUPageSize Locked
                                               ====== ==== ==== ============ ============ ============= ============= ========== ========= ============= ==== ============== =========== ======
                                               164000 5364 3210         2432            0          1200          1732       5364      1732             0    0            472         472      0

2.4 Running "ps_mem.py" and reading the memory figures for PID=100886

asciiart
# ./ps_mem.py -p 100886
----------------------------------------------------------------------------------------------------------------
 Private  +   Shared  =  RAM used       Program

  2.9 MiB + 340.0 KiB =   3.2 MiB       mc
---------------------------------
                          3.2 MiB

3 Installing "smem" and an example of its use

3.1 Downloading and "installing" smem

asciiart
# cd /install
# wget https://www.selenic.com/smem/download/smem-1.4.tar.gz
# tar -xvzf ./smem-1.4.tar.gz

3.2 Running smem

asciiart
# cd /install/smem-1.4
# ./smem

4 Installing "ps_mem.py" and an example of its use

4.1 Downloading and "installing" ps_mem.py

asciiart
# cd /install
# wget https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py
# chmod +x ps_mem.py
# ./ps_mem.py

4.2 Running ps_mem.py for PID=100886

asciiart
# /install/ps_mem.py -p 100886

4.3 Running ps_mem.py for PID=100886 with the output refreshed every second

asciiart
# /install/ps_mem.py -p 100886 -w 1

5 Real use of "smem" to measure the memory used by "mc" (Midnight Commander)

Two log files are used to measure the memory the "mc" process uses:

asciiart
+----+--------------------------------+---------------+
| ID | File                           | Size          |
+----+--------------------------------+---------------+
|  1 | /var/log/messages-20161114     | 1,5 MB        |
+----+--------------------------------+---------------+
|  2 | /var/log/messages-20161120     | 588 KB        |
+----+--------------------------------+---------------+

Measuring the memory the "mc" process uses was done in these steps:

5.1 - The output shows what the "mc" process (Midnight Commander) is using right now. USS for "mc" is 2.9 MB.

asciiart
Showing memory use
          - for one particular process (-P)
          - print the summary/total (-t)
          - print the units K,M,G,... (-k)
          - print the columns "pid", "name", "maps", "vss", "uss", "pss", "rss", "swap" (-c)
----------------------------------------------------------------------------------------------------------------
# ./smem -c 'pid name maps vss uss pss rss swap' -P /usr/bin/mc -t -k
----------------------------------------------------------------------------------------------------------------
   PID Name                      Maps      VSS      USS      PSS      RSS     Swap
100886 mc                         118   160.2M     2.9M     3.1M     5.2M        0
101240 python                      81   142.7M     4.6M     5.2M     6.7M        0
----------------------------------------------------------------------------------------------------------------
     2                            199   302.9M     7.4M     8.4M    11.9M        0

5.2 - The output shows what the "mc" process (Midnight Commander) is using with file ID 1 open for editing. USS for "mc" has risen from 2.9 to 4.2 MB.

asciiart
# ./smem -c 'pid name maps vss uss pss rss swap' -P /usr/bin/mc -t -k
----------------------------------------------------------------------------------------------------------------
   PID Name                      Maps      VSS      USS      PSS      RSS     Swap
100886 mc                         118   161.7M     4.2M     4.5M     6.6M        0
101245 python                      81   142.7M     4.6M     5.2M     6.7M        0
----------------------------------------------------------------------------------------------------------------
     2                            199   304.4M     8.8M     9.8M    13.3M        0

5.3 - The output shows what the "mc" process (Midnight Commander) is using after editing of file ID 1 has finished. The process has given back the memory it allocated for editing, and USS is comparable with output [5.1].

asciiart
# ./smem -c 'pid name maps vss uss pss rss swap' -P /usr/bin/mc -t -k
----------------------------------------------------------------------------------------------------------------
   PID Name                      Maps      VSS      USS      PSS      RSS     Swap
100886 mc                         118   160.2M     2.9M     3.1M     5.2M        0
101250 python                      81   142.7M     4.6M     5.2M     6.7M        0
----------------------------------------------------------------------------------------------------------------
     2                            199   302.9M     7.4M     8.4M    11.9M        0

5.4 - The output shows what the "mc" process (Midnight Commander) is using with file ID 2 open for editing. USS for "mc" has risen from 2.9 to 3.4 MB.

asciiart
# ./smem -c 'pid name maps vss uss pss rss swap' -P /usr/bin/mc -t -k
----------------------------------------------------------------------------------------------------------------
   PID Name                      Maps      VSS      USS      PSS      RSS     Swap
100886 mc                         118   160.7M     3.4M     3.6M     5.7M        0
101273 python                      81   142.7M     4.6M     5.2M     6.7M        0
----------------------------------------------------------------------------------------------------------------
     2                            199   303.4M     7.9M     8.9M    12.4M        0

5.5 - The output shows what the "mc" process (Midnight Commander) is using after editing of file ID 2 has finished. The process has given back the memory it allocated for editing, and USS is comparable with output [5.1] and [5.3].

asciiart
# ./smem -c 'pid name maps vss uss pss rss swap' -P /usr/bin/mc -t -k
----------------------------------------------------------------------------------------------------------------
   PID Name                      Maps      VSS      USS      PSS      RSS     Swap
100886 mc                         118   160.2M     2.9M     3.1M     5.2M        0
101275 python                      81   142.7M     4.6M     5.2M     6.7M        0
----------------------------------------------------------------------------------------------------------------
     2                            199   302.9M     7.4M     8.4M    11.9M        0

5.6 - The output shows what the "mc" process (Midnight Commander) is using right now, listing every mapping the process holds as well.

asciiart
Show memory use:
    - for one particular process (-P)
    - print the total (-t)
    - print the units K, M, G, ... (-k)
    - print every mapping (-m)
    - print the columns "pids", "map", "vss", "uss", "pss", "rss", "swap" (-c)
----------------------------------------------------------------------------------------------------------------
# ./smem -c 'pids map vss uss pss rss swap' -m -P /usr/bin/mc -t -k
----------------------------------------------------------------------------------------------------------------
PIDs Map                                           VSS      USS      PSS      RSS     Swap
   2 [vdso]                                      16.0K        0        0     8.0K        0
   2 [vsyscall]                                   8.0K        0        0        0        0
   1 /usr/lib64/gconv/gconv-modules.cache        28.0K        0     3.0K    24.0K        0
   2 /usr/lib/locale/locale-archive             202.3M        0     7.0K    84.0K        0
   1 /usr/lib64/libcom_err.so.2.1                 2.0M     8.0K     8.0K    16.0K        0
   1 /usr/lib64/libkeyutils.so.1.5                2.0M     8.0K     8.0K    16.0K        0
   1 /usr/lib64/libpcre.so.1.2.0                  2.4M     8.0K     8.0K    16.0K        0
   1 /usr/lib64/libutil-2.17.so                   2.0M     8.0K     8.0K    12.0K        0
   1 /usr/lib64/libz.so.1.2.7                     2.1M     8.0K     8.0K    20.0K        0
   1 /usr/lib64/libkrb5support.so.0.1             2.1M     8.0K     9.0K    24.0K        0
   1 /usr/lib64/libselinux.so.1                   2.1M     8.0K     9.0K    40.0K        0
   1 /usr/bin/python2.7                          12.0K     8.0K    10.0K    12.0K        0
   1 /usr/lib64/libgmodule-2.0.so.0.4600.2        2.0M     8.0K    10.0K    20.0K        0
   1 /usr/lib64/libnss_files-2.17.so              2.1M     8.0K    10.0K    40.0K        0
   1 /usr/lib64/libnss_dns-2.17.so                2.0M     8.0K    11.0K    20.0K        0
   1 /usr/lib64/python2.7/lib-dynload/_functo     2.0M     8.0K    12.0K    16.0K        0
   1 /usr/lib64/libk5crypto.so.3.1                2.2M    12.0K    13.0K    32.0K        0
   1 /usr/lib64/python2.7/lib-dynload/_locale     2.0M     8.0K    16.0K    24.0K        0
   1 /usr/lib64/python2.7/lib-dynload/grpmodu     2.0M    16.0K    16.0K    16.0K        0
   2 /usr/lib64/libdl-2.17.so                     4.0M    16.0K    16.0K    32.0K        0
   1 /usr/lib64/libgssapi_krb5.so.2.2             2.3M    12.0K    17.0K    64.0K        0
   1 /usr/lib64/python2.7/lib-dynload/_heapq.     2.0M    12.0K    18.0K    24.0K        0
   1 /usr/lib64/libresolv-2.17.so                 2.1M     8.0K    19.0K    64.0K        0
   1 /usr/lib64/libgpm.so.2.1.0                   2.0M    20.0K    20.0K    20.0K        0
   1 /usr/lib64/python2.7/lib-dynload/_collec     2.0M    12.0K    20.0K    28.0K        0
   1 /usr/lib64/python2.7/lib-dynload/_struct     2.0M    12.0K    20.0K    28.0K        0
   1 /usr/lib64/python2.7/lib-dynload/stropmo     2.0M    12.0K    20.0K    28.0K        0
   1 /usr/lib64/python2.7/lib-dynload/timemod     2.0M    12.0K    20.0K    28.0K        0
   2 /usr/lib64/libpthread-2.17.so                4.2M    16.0K    20.0K   136.0K        0
   2 /usr/lib64/ld-2.17.so                      272.0K    16.0K    23.0K   244.0K        0
   2 /usr/lib64/libm-2.17.so                      6.0M    16.0K    24.0K   148.0K        0
   1 /usr/lib64/python2.7/lib-dynload/operato     2.0M    12.0K    26.0K    40.0K        0
   1 /usr/lib64/python2.7/lib-dynload/itertoo     2.1M    24.0K    36.0K    48.0K        0
   1 /usr/lib64/libssh2.so.1.0.1                  2.2M    40.0K    40.0K    40.0K        0
   1 /usr/lib64/libssl.so.1.0.1e                  2.4M    44.0K    55.0K   124.0K        0
   2 [stack]                                    272.0K    64.0K    64.0K    64.0K        0
   1 /usr/lib64/libkrb5.so.3.3                    2.9M    68.0K    82.0K   212.0K        0
   2 /usr/lib64/libc-2.17.so                      7.5M    48.0K   111.0K     1.4M        0
   1 /usr/lib64/libcrypto.so.1.0.1e               3.9M   152.0K   199.0K   564.0K        0
   1 /usr/lib64/libglib-2.0.so.0.4600.2           3.2M    72.0K   199.0K   528.0K        0
   1 /usr/lib64/libslang.so.2.2.4                 3.1M   528.0K   528.0K   528.0K        0
   1 /usr/bin/mc                                  1.1M   704.0K   704.0K   704.0K        0
   1 /usr/lib64/libpython2.7.so.1.0               3.7M   232.0K   800.0K     1.3M        0
   2 <anonymous>                                  2.3M     1.8M     1.8M     1.8M        0
   2 [heap]                                       3.7M     3.4M     3.4M     3.4M        0
--------------------------------------------------------------------------------------------
  56 45                                         302.8M     7.4M     8.4M    11.9M        0

Current practice (checked 2026-10)

noteThe article above is kept as it was written in 2017. This section lists what has changed since and what to do instead today.
bash
$ ps -o pid,comm,vsz,rss,pss,uss -p 100886
$ cat /proc/100886/smaps_rollup

Sources:

← learnz/memory(EN | SK)