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_cachesWe 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 secondsWe 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 secondsNow 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.