Linux下哪些進程在消耗我們的Cache?

我們很容易就用free命令看到系統的cache使用量,但是你知道是哪些程序的文件在消耗cache嗎?雖然cache在嚴格意義上也是可以當做free的內存使用的,也可以通過 echo 3>/proc/sys/vm/drop_caches來主動釋放,但是你真的確定運行這條命之後,cache的數據回寫到磁盤不會造成你的系統IO飆升而出現其他問題嗎?你確定當前系統是可以清理page cache的嗎?爲了弄明白,到底是哪些文件被緩存了。今天就來寫個腳本探測一下系統進程所打開的那些文件在消耗我們的cache。


先來看一下我們的內存使用情況:


# free  
              total        used        free      shared  buff/cache   available
Mem:        3882572      762388      398412      194732     2721772     2586636
Swap:


一開始我是參考餘楓大拿的這篇文章(http://blog.yufeng.info/archives/688)需要用上高大上的System Tap來探測,這對於某些線上環境的機器來說是不可能給你安裝kernel-debug,kernel-devel-debug 幾百兆的包來跑System Tap腳本的。


然後我用到了他文章最後提到的那個工具fincore,是由國外的大拿開發的專門用來探測系統的哪些文件正在被cache。(下載地址:https://code.google.com/p/linux-ftools/source/browse/#hg%253Fstate%253Dclosed)


下載下來按照說明,簡單安裝./configure && make && make install,編譯 生成的三個工具linux-fincore、linux-fallocate、linux-fadvise 在/usr/local/bin/目錄下。


今天只用到linux-fincore,他的用法比較簡單:


# linux-fincore
fincore version 1.3.0
fincore [options] files...
  -s --summarize          When comparing multiple files, print a summary report
  -p --pages              Print pages that are cached
  -o --only-cached        Only print stats for files that are actually in cache.
  -g --graph              Print a visual graph of each file's cached page distribution.
  -S --min-size           Require that each files size be larger than N bytes.
  -C --min-cached-size    Require that each files cached size be larger than N bytes.
  -P --min-perc-cached    Require percentage of a file that must be cached.
  -h --help               Print this message.
  -L --vertical           Print the output of this script vertically.


使用過程中發現下面的這些參數貌似都不好用,輸出都是一樣的內容,先來看一個庫文件的緩存情況:


# linux-fincore -o /usr/lib64/libz.so.1.2.7 
linux-fincore: invalid option -- 'o'
filename                                                                                       size        total_pages    min_cached page       cached_pages        cached_size        cached_perc
--------                                                                                       ----        -----------    ---------------       ------------        -----------        -----------
/usr/lib64/libz.so.1.2.7                                                                     90,632                 23                  0                 23             94,208             100.00
---
total cached size: 94,208


右側顯示size(Byte), total_pages, min_cached page, cached_pages, cached_size,cached_perc。

這裏可以看到該文件的緩存率是100,就是說它是被完全被緩存起來的,這也可以理解,庫文件經常被調用,緩存起來可以提高訪問速度。


需要注意的是,他只能查看指定的文件是否是被緩存的,而不能指定目錄,因爲linux 的cache是隻緩存文件的。


fincore的工作原理是將指定的文件的相應inode data與kernel的 page cache table做對比,如果page cache table有這個inode 信息,就找該inode對應的data block的大小。因爲kernel的page cache table只存儲data block的引用而不是文件名,即文件的inode信息。所以並沒有任何一個工具運行一次就可以找出所有的文件使用緩存的情況,如果你非要對系統的所有文件都用linux-fincore查看一遍的話,那我就不跟你做朋友了:(。

所以使用linux-fincore只能加文件名,來判斷該文件是否被緩存,如果緩存,大小是多少。問題是你不能隨便猜哪個文件是否被緩存吧,我突然想到了一個方法,既然cache也是內存的一部分,那就查看哪些進程使用的物理內存最多,就找到該進程打開的文件,然後用fincore查看這些文件的緩存使用率。


在這之前,我們先看一下top輸出的VIRT, RES, SHR值的含義。來看看man手冊給我們的解釋:


VIRT  --  Virtual Memory Size (KiB)
           The total amount of virtual memory used by the task.  It includes all code, data and shared libraries plus pages that have
           been swapped out and pages that have been mapped but not used.


一個任務使用的虛擬內存的總量,包括 代碼、數據、共享庫加上已換出的頁和已經被映射出去了但是還沒被使用的頁。 簡單理解就是所有的虛擬內存中含有共享庫、共享內存、堆、棧和所有已經申請的內存空間。

利用命令查看:vsz=data + code + shared lib


$ ps -a -o pid,pmem,cmd,vsz,drs,trs
  PID %MEM CMD                            VSZ   DRS  TRS
 3870  0.0 ps -a -o pid,pmem,cmd,vsz,d 148912 148822  89
10906  0.0 screen -dr                  129744 129744   0
16116  0.0 sudo -i                     195524 195524   0
16117  0.3 -zsh                        156876 156876   0



 RES  --  Resident Memory Size (KiB)
           The non-swapped physical memory a task is using.


一個任務使用的不可交換的物理內存大小。是一個進程正在使用的內存空間(堆、棧)。


SHR  --  Shared Memory Size (KiB)
           The amount of shared memory available to a task, not all of which is typically resident.  It simply reflects memory that could be  potentially
           shared with other processes.


一個任務正在使用的共享內存大小,這個大小對該進程不是固定的,它只是簡單底反應了可以被其他進程共享的內存大小。


因爲cache使用的是物理內存,所以與swap就無關了。所以只關心RES的值。我們來寫個腳本來查看當前系統的哪些文件正在消耗我們的cache。思路是找到使用RES最高的前10個進程,然後用lsof找到該進程正在使用的文件,最後把這些文件交給fincore來處理。


#!/bin/bash
#Author: Shanker
#Time: 2016/06/08
#set -e
#set -u
#you have to install linux-fincore
if [ ! -f /usr/local/bin/linux-fincore ]
then
    echo "You haven't installed linux-fincore yet"
    exit
fi
#find the top 10 processs' cache file
ps -e -o pid,rss|sort -nk2 -r|head -10 |awk '{print $1}'>/tmp/cache.pids
#find all the processs' cache file
#ps -e -o pid>/tmp/cache.pids
if [ -f /tmp/cache.files ]
then
    echo "the cache.files is exist, removing now "
    rm -f /tmp/cache.files
fi
while read line
do
    lsof -p $line 2>/dev/null|awk '{print $9}' >>/tmp/cache.files 
done</tmp/cache.pids
if [ -f /tmp/cache.fincore ]
then
    echo "the cache.fincore is exist, removing now"
    rm -f /tmp/cache.fincore
fi
for i in `cat /tmp/cache.files`
do
    if [ -f $i ]
    then
        echo $i >>/tmp/cache.fincore
    fi
done
linux-fincore -s  `cat /tmp/cache.fincore`
rm -f /tmp/cache.{pids,files,fincore}


運行效果如下,可以看到內存使用率最高的前十個進程緩存的文件佔用了296MB的內存。


wKiom1dXyouhmMv-AADObSM6r1c155.png


當然腳本可以實現查看系統所有進程所打開的文件cache 狀態,如果你不想讓你的磁盤I/O搞成這的話,可以試試。


wKiom1dXyo2BN47PAAA4RO3JaiM346.png



參考鏈接:

http://serverfault.com/questions/278454/is-it-possible-to-list-the-files-that-are-cached

http://blog.yufeng.info/archives/688


歡迎補充!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章