Linux developers often need to deal with the memory used by processes, for example, to analyze programs for memory leaks. We might use ps, top, procrank, and Dumpsys (the last two for Android) to track and debug the process’s memory usage. The concept of VSS, RSS, PSS, USS, and some of the more important concepts involved in the above processes are familiar but not well understood, which can be detrimental to the true understanding of process memory usage. Therefore, the purpose of this article is to thoroughly analyze these four concepts, understand the relationships and differences between the quantities, and provide information that helps interpret the memory reports of various tools in order to determine the actual memory usage of Linux processes and systems, and to provide a solid theoretical basis for future analysis of memory issues.

The basic concept

  • VSS: Virtual Set Size Virtual memory (including Virtual memory shared with other processes)
  • RSS: Resident Set Size of physical memory (including memory shared with other processes)
  • PSS: Proportional Set Size of physical memory used (including memory shared with other processes in proportion)
  • USS: Unique Set Size Specifies the amount of physical memory used by a process (excluding memory shared with other processes).

For a single process, the memory footprint is generally sorted as follows: VSS >= RSS >= PSS >= USS

Concept of analytical

Android has a tool called Procrank (/ System /xbin/ Procrank) that lists the memory usage of Linux processes in order of how much they use. The memory usage reported by each process is divided into VSS, RSS, PSS and USS.

For simplicity, memory will be represented in pages rather than bytes in this description. A Linux system like ours manages memory at the lowest level with 4096 bytes of pages.

Here is a detailed explanation of what each concept means:

  1. VSS (represented as VSZ in the PS tool) represents the total accessible address space for a process. This size also includes memory that may not reside in RAM, such as memory that has not been written to after being allocated using MALloc. VSS is of little use for determining the actual memory usage of a process.

  2. RSS represents the total memory that a process actually has in RAM. RSS can be misleading because it includes the actual physical memory usage that the process shares with other processes, for example, shared libraries tend to be loaded into memory only once, regardless of how many processes use it. RSS is not an accurate representation of memory usage for a single process.

  3. PSS differs from RSS in that it reports the size of shared physical memory used in proportion to the memory shared between processes. For example, if n processes are using a shared library at the same time, the memory of the shared library is 1/n for a single process. If all three processes use a shared library of 30 pages, the library will only contribute 10 pages to the PSS reported by each process. PSS is a very useful number because when the PSS of all the processes on the system are added together, it gives a good representation of the total memory usage on the system. When a process is terminated, the shared library contributed to its PSS is proportionally allocated to the total number of PSS of other processes that are still using the library. Thus, PSS can be a bit misleading, because PSS does not accurately represent the memory returned to the entire system when the process is terminated.

  4. USS represents the total amount of physical memory used by a process, which means that the memory is exclusively used by the process. USS is a very useful number because it represents the actual incremental cost of running a particular process. USS is the total memory actually returned to the system when a process is terminated. USS is the best number to monitor when a memory leak is initially suspected in a process.

For systems using Python, there is also a great tool called Ledsmem, which reports memory statistics, including all of these categories.

NOTE: There are a few issues to NOTE here:

  1. For example, if we run two bash processes in Linux, these two bash processes actually share one piece of code. Other mmap() versions of the shared map are of course memory shared by the two processes.

  2. The memory in the shared library, not all of it, it’s just snippets of code that don’t copy-on-write that are shared across processes.

  3. USS removes all memory shared across processes, not just shared libraries.

Instance analysis

The following through an example, specific analysis of the relationship between the various quantities. Suppose there are two bash processes and one CAT process in Linux, and their ids are 1044, 1045, and 1054 respectively. VSS, RSS, PSS, and USS are calculated by the following formula:

  • VSS = 1 + 2 + 3
  • RSS = 4 + 5 + 6
  • PSS = 4/3 + 5/2 + 6
  • USS = 6

In the figure above, 4 is the part of memory where the LIBC code resides and is shared by 3 processes. 5 This memory, which is a bash code segment, is pointed to by two processes (1044 and 1045). These need to be scaled when calculating the PSS.

Monitoring tool

Linux provides ps and top commands, and Android provides procrank and dumpsys commands. For ps and top, only VSS and RSS can be found. Procrank and Dumpsys can provide PSS and USS information, and Dumpsys meminfo can find out how much memory native and Dalvik occupy respectively. In addition, Dumpsys can query a lot of useful system information, such as meminfo, cpuInfo, activity, window, wifi, account and so on.