【圖解Linux內(nèi)核】Page Cache
在資深開發(fā)的日常,經(jīng)常能遇見和Page Cache相關(guān)場(chǎng)景:
服務(wù)器的load飆高
服務(wù)器的I/O吞吐飆高
業(yè)務(wù)響應(yīng)時(shí)延出現(xiàn)大的毛刺
業(yè)務(wù)平均訪問時(shí)延明顯增加。
這些問題,很可能是由于Page Cache管理不到位引起的,因?yàn)镻age Cache管理不當(dāng)除了會(huì)增加系統(tǒng)I/O吞吐外,還會(huì)引起業(yè)務(wù)性能抖動(dòng)。
這類問題出現(xiàn)后,開發(fā)人員往往束手無(wú)策,究其原因在于他們對(duì)Page Cache的理解僅僅停留在概念上,并不清楚Page Cache如何和應(yīng)用、系統(tǒng)關(guān)聯(lián)起來,對(duì)它引發(fā)的問題自然會(huì)束手無(wú)策了。
認(rèn)識(shí)Page Cache最簡(jiǎn)單的方式,就是用數(shù)據(jù)說話,通過具體的數(shù)據(jù)你會(huì)更加深入地理解Page Cache的本質(zhì)。
為什么需要Page Cache,Page Cache的產(chǎn)生和回收是什么樣的。
最好具備一些Linux編程的基礎(chǔ),比如,如何打開一個(gè)文件;如何讀寫一個(gè)文件;如何關(guān)閉一個(gè)文件等等。
什么是Page Cache?
Page Cache到底是屬于內(nèi)核還是屬于用戶?
紅色的地方就是Page Cache,Page Cache是內(nèi)核管理的內(nèi)存,它屬于內(nèi)核。
怎么觀察Page Cache
在Linux上直接查看Page Cache的方式:
/proc/meminfo
free
/proc/vmstat 命令
內(nèi)容其實(shí)是一致的。拿/proc/meminfo命令舉例
$ cat /proc/meminfo ... Buffers: 1224 kB Cached: 111472 kB SwapCached: 36364 kB Active: 6224232 kB Inactive: 979432 kB Active(anon): 6173036 kB Inactive(anon): 927932 kB Active(file): 51196 kB Inactive(file): 51500 kB ... Shmem: 10000 kB ... SReclaimable: 43532 kB ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
可得出公式(等式兩邊之和都是112696 KB):
Buffers + Cached + SwapCached = Active(file) + Inactive(file) + Shmem + SwapCached
1
2
等式兩邊的內(nèi)容就是Page Cache。兩邊都有SwapCached,因?yàn)樗彩荘age Cache一部分。
因Buffers更依賴于內(nèi)核實(shí)現(xiàn),在不同內(nèi)核版本它的含義可能不一,而等式右邊和應(yīng)用程序的關(guān)系更直接,分析等式右邊。
Page Cache中,Active(file)+Inactive(file)是File-backed page(與文件對(duì)應(yīng)的內(nèi)存頁(yè))。平時(shí)用的mmap()內(nèi)存映射方式和buffered I/O來消耗的內(nèi)存就屬于這部分,在生產(chǎn)環(huán)境也最容易產(chǎn)生問題。
SwapCached是在打開Swap分區(qū)后,把Inactive(anon)+Active(anon)這兩項(xiàng)里的匿名頁(yè)給交換到磁盤(swap out),然后再讀入到內(nèi)存(swap in)后分配的內(nèi)存。
由于讀入到內(nèi)存后原來的Swap File還在,所以SwapCached也可以認(rèn)為是File-backed page,即屬于Page Cache。這是為了減少I/O。
SwapCached只在Swap分區(qū)打開時(shí)才有,推薦生產(chǎn)環(huán)境關(guān)閉Swap分區(qū),因?yàn)镾wap過程產(chǎn)生的I/O容易引起性能抖動(dòng)。
Page Cache中的Shmem指匿名共享映射這種方式分配的內(nèi)存(free命令中shared這一項(xiàng)),比如tmpfs(臨時(shí)文件系統(tǒng)),這部分在生產(chǎn)環(huán)境問題較少,不過多關(guān)注。
很多同學(xué)喜歡用free查看系統(tǒng)中有多少Page Cache,根據(jù)buff/cache判斷存在多少Page Cache。free也是通過解析/proc/meminfo得出這些統(tǒng)計(jì)數(shù)據(jù)的。
free的buff/cache是什么呢?
$ free -k total used free shared buff/cache available Mem: 7926580 7277960 492392 10000 156228 430680 Swap: 8224764 380748 7844016
1
2
3
4
通過procfs源碼里面的proc/sysinfo.c,可以發(fā)現(xiàn)buff/cache包括
buff/cache = Buffers + Cached + SReclaimable
1
一定要考慮到這些數(shù)據(jù)是動(dòng)態(tài)變化的,而且執(zhí)行命令本身也會(huì)帶來內(nèi)存開銷,所以這個(gè)等式未必會(huì)嚴(yán)格相等,不過你不必懷疑它的正確性。
看到free命令中的buff/cache是由Buffers、Cached和SReclaimable這三項(xiàng)組成的,它強(qiáng)調(diào)的是內(nèi)存的可回收性,即可以被回收的內(nèi)存會(huì)統(tǒng)計(jì)在這一項(xiàng)。
SReclaimable是可以被回收的內(nèi)核內(nèi)存,包括dentry和inode等。
掌握了Page Cache具體由哪些部分構(gòu)成之后,在它引發(fā)一些問題時(shí),你就能夠知道需要去觀察什么。
比如應(yīng)用本身消耗內(nèi)存(RSS)不多的情況下,整個(gè)系統(tǒng)的內(nèi)存使用率還是很高,那不妨去排查下是不是Shmem(共享內(nèi)存)消耗了太多內(nèi)存。
如果不用內(nèi)核管理的Page Cache,那有兩種思路來進(jìn)行處理:
應(yīng)用程序維護(hù)自己的Cache做更加細(xì)粒度的控制,比如MySQL就是這樣做的,MySQL Buffer Pool實(shí)現(xiàn)復(fù)雜度很高。
直接使用Direct I/O繞過Page Cache,不使用Cache了,省的去管它了。
為什么需要Page Cache?
標(biāo)準(zhǔn)I/O和內(nèi)存映射會(huì)先把數(shù)據(jù)寫入到Page Cache,這樣做會(huì)通過減少I/O次數(shù)來提升讀寫效率。我們看一個(gè)具體的例子。首先,我們來生成一個(gè)1G大小的新文件,然后把Page Cache清空,確保文件內(nèi)容不在內(nèi)存中,以此來比較第一次讀文件和第二次讀文件耗時(shí)的差異。具體的流程如下。
先生成一個(gè)1G的文件:
$ dd if=/dev/zero of=/home/yafang/test/dd.out bs=4096 count=$((1024*256))
其次,清空Page Cache,需要先執(zhí)行一下sync來將臟頁(yè)(第二節(jié)課,我會(huì)解釋一下什么是臟頁(yè))同步到磁盤再去drop cache。
$ sync && echo 3 > /proc/sys/vm/drop_caches
1
第一次讀取文件的耗時(shí)如下:
$ time cat /home/yafang/test/dd.out &> /dev/null real 0m5.733s user 0m0.003s sys 0m0.213s
1
2
3
4
再次讀取文件的耗時(shí)如下:
$ time cat /home/yafang/test/dd.out &> /dev/null real 0m0.132s user 0m0.001s sys 0m0.130s
1
2
3
4
通過這樣詳細(xì)的過程你可以看到,第二次讀取文件的耗時(shí)遠(yuǎn)小于第一次的耗時(shí),這是因?yàn)榈谝淮问菑拇疟P來讀取的內(nèi)容,磁盤I/O是比較耗時(shí)的,而第二次讀取的時(shí)候由于文件內(nèi)容已經(jīng)在第一次讀取時(shí)被讀到內(nèi)存了,所以是直接從內(nèi)存讀取的數(shù)據(jù),內(nèi)存相比磁盤速度是快很多的。這就是Page Cache存在的意義:減少I/O,提升應(yīng)用的I/O速度。
所以,如果你不想為了很細(xì)致地管理內(nèi)存而增加應(yīng)用程序的復(fù)雜度,那你還是乖乖使用內(nèi)核管理的Page Cache,它是ROI(投入產(chǎn)出比)相對(duì)較高的一個(gè)方案。
Page Cache的不足之處也是有的,這個(gè)不足之處主要體現(xiàn)在,它對(duì)應(yīng)用程序太過于透明,以至于應(yīng)用程序很難有好方法來控制它。
Page Cache對(duì)應(yīng)用提升I/O效率而言是一個(gè)投入產(chǎn)出比較高的方案,所以它的存在還是有必要的。
Linux
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。