Understanding Linux memory usage

In Linux, you can retrieve statistics on memory usage via the “free” command. By default, free will report the current memory statistics in kilobytes, but you can optionally specify -b for bytes, -m for megabytes, -g for gigabytes, and -h for human readable, which will automatically infer the units and append a “B”, “K”, “M”, “G”, or “T” to the values as appropriate for each value. I tend to prefer using megabytes or gigabytes, depending on the memory capacity of the system and the desired granularity of the data. I tend to find human readable form to be a pain, in that it may use different unit types for different values, and this prevents direct (and more visual) comparison of the values. Clearly 1 megabytes is more than 100 kilobytes, but it takes some additional mental processing to compare 1M and 100K, especially when various values and unit types are involved. You can also supply -s followed by a numeric value as an argument which will specify the interval in seconds at which the memory statistics are continually retrieved.

As I started writing this, I realized that the output of free has actually changed in recent releases (procps-ng >= 3.3.10). I’m still going to cover the earlier output of free, as this will actually elucidate why the output of free was changed in the more recent releases.

Let’s take a look at the pre-3.3.10 output.

$ free -m
             total       used       free     shared    buffers     cached
Mem:           925        890         34         27         17        777
-/+ buffers/cache:         95        830
Swap:           99         67         32

The first row contains the statistics for the system’s physical memory. Let’s break down the columns one by one.

  • total => The total amount of memory. On this machine (a Raspberry Pi 3 Model B), we can observe that 925MB of physical memory are present.
  • used => The amount of memory currently in use. (Note: this value is calculated differently in 3.3.10, as we’ll cover.)
  • free => The amount of memory that is not in use.
  • shared => The amount of memory that is shared between processes.
  • buffers => The amount of memory that is used for kernel buffers. Kernel buffers are generally utilized for temporary I/O storage.
  • cached => The amount of memory that is cached by the system. This cached data is used to improve system performance.

Making sense of it all

According to the output from free, ~890MB of the RAM are “used”, while ~34 MB are “free”. You might think this is indicative of a system that is short on memory, but that is not so. Memory that is being used for kernel buffers or the disk cache counts as “used” memory and subtracts from the amount of “free” memory. Roughly speaking (more on this later), the ~777MB in use by the disk cache is not strictly required, such that the memory could be used by an application that needs it.

Disk caching on Linux is designed to be unobtrusive, such that performance may be improved without taking away memory from running processes. Generally speaking, your “free” memory will be low, as Linux will use memory for disk caching to improve system performance.

This brings us to the second row. In the second row, the amounts in the buffers and cache are subtracted from the used memory, and this difference is added to the free memory. This row serves as an estimate of the amount of memory that is unavailable (used) vs available (free). This rough estimate from adding to and subtracting from the amount of memory in the buffers and disk cache, as well as the “used” amount reported, have been updated in the more recent releases of procps-ng (>= 3.3.10), as we will show below.

The final row relates to the allocated swap space. Swap space is space on disk that is generally utilized when there is not enough physical memory present. It acts as a temporary location for swapping in and out pages of memory as needed. (A page is a chunk of memory that is the primary unit of memory in which the kernel and CPU deals. Many posts could go into this topic…)

What changed in the newer versions of free?

Let’s take a look.

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          31953        1789        5818        1619       24345       27443
Swap:         16063         853       15210

In the recent versions of free, used does not include buffers and cached data, as you can see from the relevant commit.

A new column “available” has been added in lieu of the second line which excluded the amounts from buffers and cached data in “used” and added them to “free”. In Linux kernels older than 2.6.27, the reported available amount is exactly the same as the free value of the -/+ buffers/cached row from the older version of free. In later versions of the Linux kernel, free takes into account page cache and also accounts for the fact that not all reclaimable memory slabs can actually be reclaimed. For more details, see the relevant commit.

Further resources

If this whets your appetite, you may also be interested in checking out the vmstat utility. You may also want to check out some of the more general purpose monitoring tools that also include memory statistics such as top, htop, sar, and atop. I’ll probably write something about these at some point. If you want to dive in further on memory-specific utilities, you may also want to check out swapon, slabtop, and smem. Generally speaking, these tools fetch their source data from the /proc pseudo filesystem, which will undoubtedly be a post in the near future.