A few months ago while setting up a few cloud servers to host one of my applications. I started running into an interesting issue while building Docker containers. During the docker build
execution my servers ran out of memory causing the Docker build to fail.
The servers in question only have about 512MB
of RAM and the Docker execution was using the majority of the available memory. My solution to this problem was simple, add a swap file.
A swap file is a file that lives on a file system and is used like a swap device.
While adding the swap file I thought this would make for an interesting article. Today's post is going to cover how to add a swap file to a Linux system. However, before we jump into creating a swap file, let's explore what exactly swap is and how it works.
What is swap
When Linux writes data to physical memory, or RAM it does so in chunks that are called pages. Pages can vary in size from system to system but in general a page is a small amount of data. The Linux kernel will keep these pages in physical memory for as long as it has available memory to spare and the pages are relevant.
When the kernel needs to make room for new memory pages it will move some memory pages out of physical memory, where the destination is usually to a swap device. Swap devices are hard-drive partitions or files within a file system used to expand the memory capacity of a system.
A simple way to think of swap is to think of it as an overflow area for system memory. With that thought, the general rule of thumb is that memory pages being written to swap is a bad thing. In my case however, since the only time I require swap is during the initial build of my Docker containers. Swapping isn't necessarily a bad thing.
In fact, my use case is exactly the reason why swap exists. I have a process that requires more memory than what is available on my system, and I would prefer to use some disk space to perform the task rather than add memory to the system. The key is that my system does not swap during normal operations, only during the Docker build execution.
Determining if a system is Swapping
In summary, Swapping is only a bad thing, if it happens during unexpected times. A simple way to determine if a system is actively swapping is to run the vmstat
command.
$ vmstat -n 5 5
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 100 207964 22056 129964 0 0 14 1 16 32 0 0 100 0 0
0 0 100 207956 22056 129956 0 0 0 0 16 26 0 0 100 0 0
0 0 100 207956 22064 129956 0 0 0 2 16 27 0 0 100 0 0
0 0 100 207956 22064 129956 0 0 0 0 14 23 0 0 100 0 0
0 0 100 207956 22064 129956 0 0 0 0 14 24 0 0 100 0 0
The vmstat
command can be used to show memory statistics from the system in question. In the above there are two columns, si
(Swapped In) and so
(Swapped Out) which are used to show the number of pages swapped in and swapped out.
Since the output above shows that the example system is neither swapping in, or swapping out memory pages, we can assume that swapping on this server is probably not an issue. The fact that at one point the system has swapped 100KB
of data does not necessarily mean there is an issue.
When does a system swap
A common misconception about swap and Linux is that the system will swap only when it is completely out of memory. While this was mostly true a long time ago, recent versions of the Linux kernel include a tunable parameter called vm.swappiness
. The vm.swappiness
parameter is essentially an aggressiveness setting. The higher the vm.swappiness
value (0
- 100
), the more aggressive the kernel will swap. When set to 0
, the kernel will only swap once the system memory is below the vm.min_free_kbytes
value.
What this means is, unless vm.swappiness
is set at 0
. The system may swap at any time, even without memory being completely used. Since by default the vm.swappiness
value is set to 60
, which is somewhat on the aggressive side. A typical Linux system may swap without ever hitting the vm.min_free_kbytes
threshold.
This aggressiveness does not often impact performance (though it can in some cases) because when the kernel decides to start swapping it will pick memory pages based on the last accessed time of those pages. What this means is, data that is frequently accessed is kept in physical memory longer, and data that is not frequently accessed is usually the primary candidates for moving to swap.
Now that we have a better understanding of swap, let's add a swap device to the cloud servers in question.
Adding a swap device
Adding a swap device is fairly easy and can be done with only a few commands. Let's take a look at the memory available on the system today. We will do this with the free
command, using the -m
(Megabytes) flag.
$ free -m
total used free shared buffers cached
Mem: 489 281 208 0 17 126
-/+ buffers/cache: 136 353
Swap: 0 0 0
From the free
command's output we can see that this server currently has no swap space at all. We will change that by creating a 2GB
swap file.
Creating a swap file
The first step in creating a swap file is to create a file with the dd
command.
$ sudo dd if=/dev/zero of=/swap bs=1M count=2048
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB) copied, 5.43507 s, 395 MB/s
The reason we used dd
to create the file is because we can create more than a simple empty file. With the dd
command above we created a 2GB
file (writing 1MB
chunks 2048
times) with the contents being populated from /dev/zero
. This gives us the data space that will make up the swap device. Whatever size we make the file in this step, is the size the swap device will be.
With the file created, we can now use the mkswap
command to make the file a swap device.
$ sudo mkswap /swap
Setting up swapspace version 1, size = 2097148 KiB
no label, UUID=0d64a557-b7f9-407e-a0ef-d32ccd081f4c
The mkswap
command is used to setup a file or device as a swap device. This is performed by formatting the device or file as a swap partition.
Mounting the swap device
With our file now formatted as a swap device we can start the steps to mount it. Like any other filesystem device, in order to mount our swap device we will need to specify it within the /etc/fstab
file. Let's start by appending the below contents into the /etc/fstab
file.
/swap swap swap defaults 0 0
With the above step complete, we can now mount the swap file. To do this we will use the swapon
command.
$ sudo swapon -a
The -a
flag for swapon
tells the command to mount and activate all defined swap devices within the /etc/fstab
file. To check if our swap file was successfully mounted we can execute the swapon
command again with the -s
option.
$ sudo swapon -s
Filename Type Size Used Priority
/swap file 2097148 0 -1
From the above we can see that /swap
, the file we created is mounted and currently in use as a swap device. If we were to re-run the free
command from above we should also see the swap space available.
$ free -m
total used free shared buffers cached
Mem: 489 442 47 0 11 291
-/+ buffers/cache: 139 350
Swap: 2047 0 2047
In the previous execution of the free
command the swap size was 0
and now it is 2047 MB
. This means we have roughly 2GB
of swap to use with this system.
A useful thing to know about Linux is that you can have multiple swap devices. The priority
value of the swap device is used to determine in what order the data should be written. When 2 or more swap devices have the same priority
swap usage is balanced across both. This means you can gain some performance during times of swap usage by creating multiple swap devices on different hard-drives.
Got any other swap tips? Add them below in the comments.