Thoughts

13 Nov: What's in the page cache?

Its well known that when you look at free memory on Linux, you need to bear in mind that the page cache is included in total memory usage. In this example there's 987MB of RAM available, 92MB is used, 828MB is used for buffers/cache, leaving 66MB free, but 649MB available as cache contents can be evicted if needed:
# free -m
              total        used        free      shared  buff/cache   available
Mem:            987          92          66          49         828         649

The page cache takes up the majority of buffers/cache. There are occasionaly cicumstances where you want to tune how the cache evictions happen, but usually the kernel deals with it just fine.

The page cache contains the contents of files which are mapped into RAM when they are read or written(1) to speed up access next time they're needed. If there's no more space in the cache, if more memory is needed by applications, or if the system looks to be under pressure, the least recently used (LRU) pages are evicted. The contents of the page cache doesn't include filenames, but we can do a reverse looked to see whether the pages from a file are in cache using mincore(2). There's a number of tools that wrap this system call, including pcstat, linux-ftools and vmtouch. Here's an example with vmtouch:

Clear the page cache (only do this for testing!):

# echo 1 > /proc/sys/vm/drop_caches
We can see now that none of these MyISAM data files are cached:
# vmtouch /var/lib/mysql/mysql/*.MYD
           Files: 22
     Directories: 0
  Resident Pages: 0/151  0/604K  0%
         Elapsed: 0.00029 seconds
We can also show details on each file:
# vmtouch /var/lib/mysql/mysql/help_topic.MYD -v
/var/lib/mysql/mysql/help_topic.MYD
[                                                           ] 0/118
           Files: 1
     Directories: 0
  Resident Pages: 0/118  0/472K  0%
         Elapsed: 0.000112 seconds
Now read some data and check again:
# mysql -e 'SELECT name FROM mysql.help_topic WHERE help_topic_id = 300;'
# vmtouch /var/lib/mysql/mysql/help_topic.MYD -v
/var/lib/mysql/mysql/help_topic.MYD
[                                o                          ] 1/118
           Files: 1
     Directories: 0
  Resident Pages: 1/118  4K/472K  0.847%
         Elapsed: 0.00011 seconds

The "o" shows pages in the page cache, so in this case the SELECT statement read a single 4K page into RAM.

You can also choose to add (-t) or evict (-e) all pages from a file:

# vmtouch /var/lib/mysql/mysql/help_topic.MYD -tv
/var/lib/mysql/mysql/help_topic.MYD
[OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO] 118/118

           Files: 1
     Directories: 0
   Touched Pages: 118 (472K)
         Elapsed: 0.003222 seconds

This information can help you identify what's the contents of the page cache. It might help you see inefficient reads of data, or identify strange behaviour of cache usage seen in "free".

Finally, what about performance of the page cache? cachestat, part of perf-tools is a great way to see how often reads are having to read from disk because the required page isn't in the cache:

# ./cachestat -t
Counting cache functions... Output every 1 seconds.
TIME         HITS   MISSES  DIRTIES    RATIO   BUFFERS_MB   CACHE_MB
15:56:10      323      125        0    72.1%            0         79
15:56:11      341        0        0   100.0%            0         79
15:56:12     3162     1729        0    64.6%            3         83
15:56:13      579      312        1    65.0%            4         83
15:56:14    26458     3783        6    87.5%           17         85
15:56:15    24124     2932        3    89.2%           28         86
15:56:16    38967     1975        0    95.2%           36         86
15:56:17    36877     2337        6    94.0%           45         86
15:56:18    10835     1891        0    85.1%           52         86
15:56:19      629        1        6    99.8%           52         86
15:56:20      341        0        0   100.0%           52         86
15:56:21      351        0        3   100.0%           52         86
[1] In fact, the application can tell the kernel not to add this file to the cache using fadvise FADV_DONTNEED. For example, there's no benefit to filling the cache with streaming data which will never be reread.
© 2017