Feb 19, 2011

Cached memory in Linux

I am sure that there are many people that if they saw the following output of 'top', they would say that I have a problem with my free memory... they would be wrong.

[root@zabbix ~]# top
Mem:   4044540k total,  4007540k used,    37000k free,   156336k buffers
Swap:  2097144k total,        0k used,  2097144k free,  2086808k cached

The previous data correspond to a Zabbix installation where the free memory is around 37 MB, but the cached memory is more than 2 GB. What is happening here?

The answer is straightforward: Linux always tries to use all available memory, and thereby, it caches all read data. If at any moment an application needs memory, Linux will free it from the cached memory. This way of acting is pretty good because you will have better performance having the more frecuent data into the memory.

Really you will have a serious problem when your free memory is low, further your cached memory too and on top of all that, your system begins to swap.

Also say that other excellent data from the above 'top' is the swap memory value: 0. A well configured Linux system never should utilize swap. The key parameter for this purpose is swappiness. I usually set it with a value of 20.

[root@zabbix ~]# cat /proc/sys/vm/swappiness

There is a quick manner to force to the operating system so as to free the cached memory: changing the value of the drop_caches variable.

[root@zabbix ~]# cat  /proc/sys/vm/drop_caches

[root@zabbix ~]# sync ; echo 1 > /proc/sys/vm/drop_caches

[root@zabbix ~]# top
Mem:   4044540k total,  1756996k used,  2287544k free,     1572k buffers
Swap:  2097144k total,        0k used,  2097144k free,    62564k cached

We can demonstrate the cached memory operation through an easy bash script. The program will search twice the word "test" inside all files of the /var/log/httpd directory.

[root@zabbix ~]# cat script.sh

for (( i=0; i<2; i++))
   free -o -m
   /usr/bin/time -f "\nSeek time: %e sg\n" grep -r test /var/log/httpd/ > /dev/null

[root@zabbix ~]# ./script.sh
             total       used       free     shared    buffers     cached
Mem:          3949       1712       2237          0          2        101
Swap:         2047          0       2047

Seek time: 3.76 sg

             total       used       free     shared    buffers     cached
Mem:          3949       2003       1946          0          3        412
Swap:         2047          0       2047

Seek time: 0.50 s

In the first loop you can see that the cached memory was 101 MB and it spent 3.76 sg looping through all files. But in the second loop, the 'grep' command spent 0.5 sg because the files were already cached on memory (its size grew from 101 MB to 412 MB).

If we take a look at the size of the /var/log/httpd directory, we can appreciate that the cached memory increment practically matchs with the size of that directory.

[root@zabbix ~]# du -shx /var/log/httpd/
318M     /var/log/httpd/


  1. You can check the classic yet interesting:


    Basically it's as easy as reading free output ;)

  2. Thanks Juanjo!

    The examples used are really clear.