509

When I open a RAM-intensive app (VirtualBox set at 2GB of RAM), some swap space is generally used, depending on what else I have open at the time.

However, when I quit that last application, the 2GB of RAM is freed up, but the same swap space use remains.

For example, right now, about two hours after having closed VirtualBox, I have 1.6GB free RAM and still 770MB in swap.

How can I tell Ubuntu to stop using that swap and to revert to using the RAM?

Flyk
  • 1,480
  • 3
  • 18
  • 24
jfoucher
  • 24,444

8 Answers8

726

The Linux kernel underlying Ubuntu will automatically "swap in" those pages from disk to RAM as needed, so in general I'd say just let it happen naturally.

However, if you really feel that you need to force it, (I can see a scenario where you would want to know the system will be responsive later) you can momentarily disable and re-enable swap

sudo swapoff -a
sudo swapon -a

OR alternatively as a single line

sudo swapoff -a; sudo swapon -a

Be careful doing this, as you may make your system unstable, especially if its already low on RAM. Be sure to have enough free RAM in your system, or you might not be able to free the swap and the OOM-Killer would end up killing some of your processes.

Note that the swapoff may take a while. This is particularly true if you have lot of swap to be swapped off.

SpamapS
  • 20,110
226

Just because swap is allocated, doesn't mean it's being 'used'. Whilst programs like system monitor and top will show some of your swap space being allocated (in your example 770MB) that doesn't mean that the system is actively swapping in/out.

To find out if anything is swapping in/out you can use the vmstat command. Leave it running a few seconds to settle down and watch the si (swapin) and so (swapout) columns. If nothing is happening then there is no reason to be concerned.

Here's the output of running vmstat 1, where you can see my machine is not swapping at all.

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0  78588 230788   9596  72196    0    0     0     0  543  652 12  6 78  0
 0  0  78588 230780   9596  72196    0    0     0     0  531  410  1  0 99  0
 0  0  78588 230796   9596  72196    0    0     0     0  300  335  1  1 97  0
 1  0  78588 230788   9608  72224    0    0    40     0  737  762  4  4 84  8
 5  0  78588 230788   9608  72224    0    0     0     0  415  385  9  3 84  0
 0  0  78588 230540   9616  72224    0    0     0    44  611  556 55  5 31  0
 0  0  78588 230532   9616  72224    0    0     0     0  574  662  1  6 89  0

Yet here in top you can see I have swap space allocated:-

Mem:    475236k total,   245076k used,   230160k free,     9720k buffers
Swap:   491512k total,    78588k used,   412924k free,    72476k cached
Yi Jiang
  • 1,206
popey
  • 24,549
189

You can also set your "swappiness" value from the default of 60, this way the swap won't grow so large to begin with. Why the shipping default is set to 60 when the recommended value is 10 perplexes me. From the Ubuntu SwapFAQ:

The default setting in Ubuntu is swappiness=60. Reducing the default value of swappiness will probably improve overall performance for a typical Ubuntu desktop installation. A value of swappiness=10 is recommended, but feel free to experiment.

By changing this value to 10 or even 0, you can add a significant and perceivable speed boost to an older system with a slow drive. Setting this value to 0 does not turn swap off for Linux kernel 3.4 and below but with 3.5+ it does so you will want to use a value of 1 if you want to keep it on its lowest setting*.

I see no reason not to set this to 0 since anything that hits disk is slower than RAM. I have 8 virtual cores, a fast SSD & 8 GB of memory and my swap is set to 0. As of this moment I have 3 virtual machines running, my memory usage is 7.1 of 7.7 GB, my used swap is only at 576KB of 952MB and all systems are running smoothly!

From the Ubuntu SwapFAQ:

The swappiness parameter controls the tendency of the kernel to move processes out of physical memory and onto the swap disk. Because disks are much slower than RAM, this can lead to slower response times for system and applications if processes are too aggressively moved out of memory.

  1. swappiness can have a value of between 0 and 100
  2. swappiness=0 tells the kernel to avoid swapping processes out of physical memory for as long as possible
  3. swappiness=100 tells the kernel to aggressively swap processes out of physical memory and move them to swap cache

Below are basic instructions for checking swappiness, emptying your swap and changing the swappiness to 0:

To check the swappiness value:

cat /proc/sys/vm/swappiness

To temporarily set swap to 0 (as suggested by SpamapS):

This will empty your swap and transfer all the swap back into memory. First make sure you have enough memory available by viewing the resources tab of gnome-system-monitor, your free memory should be greater than your used swap. This process may take a while, use gnome-system-monitor to monitor and verify the progress.

sudo swapoff --all

To set the new value to 0:

sudo sysctl vm.swappiness=0 

To turn swap back on:

sudo swapon --all

To permanently set swappiness to 0:

  1. sudoedit /etc/sysctl.conf
  2. Add this line vm.swappiness = 0
  3. sudo shutdown -r now # restart system

* With kernel version 3.5+ setting swappiness to 0 does turn it off entirely and a setting of 1 is recommended if you want the lowest swappiness algorithm. source: https://www.percona.com/blog/2014/04/28/oom-relation-vm-swappiness0-new-kernel/

Elijah Lynn
  • 3,928
63

I've found that emptying swap can help a lot on systems with slow disks and limited RAM. Of course, as already mentioned, the way to do this is to run sudo swapoff -a; sudo swapon -a. The problem here is that if there's insufficient RAM, doing so will cause all sorts of problems.

I've written a script that I call toggle_swap that has worked for me for the last several years. It checks for enough free RAM before actually disabling the swap. Here it is:

#!/bin/bash

free_data="$(free)"
mem_data="$(echo "$free_data" | grep 'Mem:')"
free_mem="$(echo "$mem_data" | awk '{print $4}')"
buffers="$(echo "$mem_data" | awk '{print $6}')"
cache="$(echo "$mem_data" | awk '{print $7}')"
total_free=$((free_mem + buffers + cache))
used_swap="$(echo "$free_data" | grep 'Swap:' | awk '{print $3}')"

echo -e "Free memory:\t$total_free kB ($((total_free / 1024)) MB)\nUsed swap:\t$used_swap kB ($((used_swap / 1024)) MB)"
if [[ $used_swap -eq 0 ]]; then
    echo "Congratulations! No swap is in use."
elif [[ $used_swap -lt $total_free ]]; then
    echo "Freeing swap..."
    sudo swapoff -a
    sudo swapon -a
else
    echo "Not enough free memory. Exiting."
    exit 1
fi
27

After mucking around with swappiness for a couple of days, I've come to the conclusion that the kernel should be left to its own devices. It knows what it's doing, and it's optimized to give you the best experience.

Unless you have a really good reason for wanting that disk back, I'd leave it be.

Erigami
  • 4,536
2

New anser 2023!

Some tips and tricks

In addition to all existing answer I want to share some tricks I use.

Reading free's output

First, ensure that output of free is not localized, for this you have to prepend command by LANG=C free -k:

               total        used        free      shared  buff/cache   available
Mem:        32739720     9436264     8704992      883044    15959152    23303456
Swap:       23437308     5450752    17986556

Where, if you compute buff/cache + available the result will be bigger than total! This is wrong!!

Just consider if available mem is bigger than used swap, before purging swap!

msgs=("NOT " "")
{ # read `free` output, ignore 1st line and all values but free and swaped.
    read _
    read -r _{,,,,,} avail
    read -r _ _ swaped _
} < <(LANG=C free -k)
printf 'Avail: %d swaped: %d Can %sunswap!\n' \
           "$avail" "$swaped" "${msgs[ avail > swaped ]}"
 Avail: 23303456 swaped: 5450752 Can unswap!

Alternative using /proc/meminfo instead of free

Accessing directly /proc/meminfo instead of running a fork to free, you could obtain same values by:

msgs=("NOT " "")
while read field val _; do
    case $field in
        MemAvailable: ) avail=$val ;;
        SwapTotal: )    declare -i swaped=$val ;;
        SwapFree: )     swaped+=-$val; break ;;
    esac
done < /proc/meminfo
printf 'Avail: %d swaped: %d Can %sunswap!\n' \
           "$avail" "$swaped" "${msgs[ avail > swaped ]}"
 Avail: 23303456 swaped: 5450752 Can unswap!

Purging swap swapoff -a.

I've build a little script that

  • correctly parse free's output,
  • show human readable swaped and avail memory,
  • offer to run swapoff - swaponn loop if user don't interact
  • then compute elapsed time used to unswap.

There is my script, based on bash V>5.0:

#!/bin/bash

msgs=("NOT " "") while read field val _; do case $field in MemAvailable: ) avail=$val ;; SwapTotal: ) declare -i swaped=$val ;; SwapFree: ) swaped+=-$val; break ;; esac done < /proc/meminfo

txtsize() { # Convert integer into readable string, store result in $2 varname local i=$(($1>=1<<50?5:$1>=1<<40?4:$1>=1<<30?3:$1>=1<<20?2:$1>1023?1:0)) local a=(K M G T P) ((i>4?i+=-2:0)) && a=(${a[@]:2}) && set -- $(($1>>20)) $2 local r=00$((1000$1/(1024*i))) printf -v $2 %.2f%s ${r::-3}.${r: -3} ${a[i]} }

txtsize $avail havail txtsize $swaped hswaped printf 'Avail: %s (%d) swaped: (%s) %d Can %sunswap!\n'
"$havail" $avail "$hswaped" $swaped "${msgs[ avail > swaped ]}"

if (( avail > swaped )); then
    if read -sn 1 -t 5 -p\
        'Proceed in 5 seconds. Hit any key to stop now. '; then
        echo $'\nUser abort.'
            exit 0
    fi
    echo
    elapsedTime=${EPOCHREALTIME/.}
    swapoff -a
    elapsedTime=00000$(( ${EPOCHREALTIME/.} - elapsedTime ))
    swapon -a
    elapsedMin=$(( 10#$elapsedTime / 60000000 ))
    elapsedSec=00000$(( 10#$elapsedTime % 60000000 ))
    printf 'Swap: %s purged in %d minutes and %.3f secs (%.4f").\n' \
        "$hswaped" "$elapsedMin" ${elapsedSec::-6}.${elapsedSec: -6} \
        ${elapsedTime::-6}.${elapsedTime: -6}

fi    

His ouptut look like:

Avail: 23.86G (25023596) swaped: (1.14G) 1192460 Can unswap!
Proceed in 5 seconds. Hit any key to stop now. 
Swap: 1.14G purged in 1 minutes and 51.166 secs (111.1661").

This script require root privilege. But you could edit them to add sudo before swapoff -a and swapon -a.

From there, as this opereation could take some time, I've built a Full purgeSwap script, showing progression with a nice progress bar and compute end time estimation, you my download here: purgeSwap.sh.

This answer is linked to this other one: How to find out which processes are using swap space in Linux?

About swapiness

I'm not totally convinced on how this compute percent of used memeory: including swap or not... For my tests, I'v seen swaping a lot before reaching percents configured in this kernel variable.

Anyway, for my servers, I still use:

echo 10 > /proc/sys/vm/swappiness

for running system that was not already configured by:

echo >/etc/sysctl.d/90-swapiness.conf  'vm.swappiness = 10'

before last reboot.

Use of vmstat 1 and instant graphs.

If you run:

vmstat 1

You will see regular dump, every 1 seconds of memory status.

I often use this, then, as I like graphical presentation, I've build (in 2009, it's not new, but still usefull) a perl CGI, that could work in standalone mode and push a little web server:

http://perso.f-hauri.ch/~felix/marcm/vmstat.cgi

This script is self-downloadable, work as a CGI in any web server, but could be used directly on poor systems, they will listen his own TCP port. Graphics are drawn in svg and rendered directly by your browser.

Sample of use:

wget -O vmstat.pl http://perso.f-hauri.ch/~felix/marcm/vmstat.cgi/download/vmstat.cgi
LANG=C perl vmstat.pl 
CGI::Pretty is DEPRECATED and will be removed in a future release. Please see https://github.com/leejo/CGI.pm/issues/162 for more information at /usr/share/perl5/CGI/Pretty.pm line 20.
Server started at port 8881

Yes, it's an old script Don't run them as root!!.

...Then you could connect with a browser:

http://ip.add.re.ss:8881/

http://127.0.0.1:8881/?delay=1&width=1800&height=80

Here 1'800 dots with a delay of 1 seconds make half hour graphs.

0

Tell the vm to not be so swappy, by resucing the swappiness, by

sudo sysctl vm.swappiness=10

or even not be swappy as much as possible by

sudo sysctl vm.swappiness=0

Please read the documentation of swapfile here: https://help.ubuntu.com/community/SwapFaq

-3

It doesn't affect performance if your swap space is occupied. The only performance penalty is is stuff is going in/out of swap. If nothing is being swapped in/swapped out, then you don't have to worry about anything.

Amandasaurus
  • 1,836