如何控制Linux清理cache機制?
可透過調節 min_free_kbytes 來達到類似目的
最簡單的echo 1 >/proc/sys/vm/drop_caches
那我來自己回答一下吧。 後來我已經找到原因了。
先說結論:
記憶體突降的原因是因為記憶體碎片過多, 核心發生了memory compaction
整個分析過程
首先, 我對伺服器出現問題的時間點前後的sar日誌進行了分析。
當時得到的現象是這樣子的:
分析記憶體變化情況(使用
sar -r
), 發現記憶體突降, 而且突降之後, 系統的記憶體並沒有馬上回升, 而是維持在一個低位很久
同時, 觀察到記憶體低位, 系統卡頓這段時間的換頁和swap情況 (使用
sar -B -S
), 發現:
pageout資料基本沒有變化
沒有大量的swap換進換出操作
pagein這時候突增, 並且維持在高位, major fault突增
pgscank 這個數值保持高位, %vmeff 保持在100%。
其中, paging的資訊給了我線索。 透過查資料, 發現pgscank表示的是Linux當中的負責記憶體回收的執行緒kswapd掃描的頁的數量, 而%vmeff表示被kswapd掃描的頁當中, 有多少頁的資料被踢出去了換成其他頁資料了(這個有個術語叫page steal, 在sar -B裡面的pgsteal/s就表示這個值) 。
這說明當時, 應該是kswapd自身觸發了記憶體的突降, 並且它在不斷掃面現有的page, 並換入新的page。
此時, 其實還是沒有實質性進展。 直到有一次, 我們幸運地正好遇到了記憶體突降的時間視窗。 於是我們趕緊上線分析
使用sar -r 和 sar -B -S 和之前的現象一致
檢視top, 我發現系統kswapd的執行緒CPU佔用率100%, 說明當時kswapd在不停努力工作中, 這個和之前的分析相吻合
然後, 直接檢視kswapd程序對應的函式呼叫的時間佔比, (使用perf top), 這時候, 我發現了原因, 此時
kswapd執行緒大部分時間都在做compact memory
!
然後我進一步看了一下memory compaction的觸發條件, 主要是Linux記憶體分配使用的buddy algorithm 在新分配記憶體一個較大的記憶體時, 找不到符合條件的連續頁, 於是觸發了memory compaction。 這個可以透過
cat /proc/buddyinfo
進行檢視。
解決方法
那剩下的問題就是如何限制系統減少出現memory compaction的機率。 查閱資料後, 發現Linux有一個引數是控制這個的:
/proc/sys/vm/extfrag_threshold
這個引數是一個0 ~ 1000的整數。 如果出現記憶體不夠用的情況, Linux會為當前系統的記憶體碎片情況打一個分, 如果超過了extfrag_threshold這個值, kswapd就會觸發memory compaction 。 所以, 這個值設定接近1000, 說明系統在記憶體碎片的處理傾向於把舊的頁換出, 以符合申請的需要; 而設定接近0, 表示系統在記憶體碎片的處理傾向於做memory compaction。
由於這臺機器在做memory compaction的時候對效能造成的影響太大, 於是
我把extfrag_threshold這個值從系統預設的500設定到了最大1000
設定完了之後, 這臺機器就再也沒出現過類似問題, 問題解決。
剩下的疑問
我只是透過現象觀察到做memory compaction的時候系統IO增高, 但是我還是不是很理解為什麼做memory compaction會涉及到大量的pagein操作, 並且維持時間如此之久?
其他說明
如果真的出現了memory compaction, 導致系統卡頓的情況, 可以透過下面2步手工縮短處理過程:
echo
1
> /proc/sys/vm/drop_caches
echo
1
> /proc/sys/vm/compact_memory
這個實質就是減少memory compaction的記憶體總量, 然後手工去整理。 測試發現效果不錯
參考
http://
ftp。dei。uc。pt/pub/linux
/kernel/people/andrea/patches/v2。6/2。6。34/transparent_hugepage-24/memory-compaction-extfrag_threshold
https://
serverfault。com/a/74606
7
https://www。
kernel。org/doc/Document
ation/sysctl/vm。txt
1 Linux下記憶體佔用多的原因
當linux第一次讀取一個檔案執行時,一份放到一片記憶體中cache起來,另一份放入執行程式的記憶體中,正常執行,當程式執行完,關閉了,cache中的那一分卻沒有釋放,第二次執行的時候,系統先看看在記憶體中是否有一地次執行時存起來的cache中的副本,如果有的話,直接從記憶體中讀取,那樣,速度就快多了。
說明這種情況的很典型的例子是啟動firefox,由於firefox程式很大,因此第一次讀取執行的時候很慢,尤其在速度不快的機器上,但是當你徹底關閉了firefox,ps看不到一個firefox程序,第二次再啟動的時候就比第一次明顯快很多,這是由於這次系統是直接從cache中讀取的firefox來執行,並不是從磁碟上讀取的。
再有一個例子:我們頻繁使用的ls命令等基本命令,你執行的時候根本看不到硬碟燈閃,因為這些常用的命令都是再第一次執行後就儲存在cache中的,以後就一直從記憶體中讀出來執行。
如果cache佔用的記憶體過多了,影響正常執行程式需要的記憶體,那麼會釋放掉一部分cache記憶體,但是總量會保持一個很高的值,所以,linux總是能最大限度的使用記憶體,就算加到16G,32G記憶體,也會隨著不斷的IO操作,記憶體的free值會慢慢減少到只有幾M,想要記憶體不發生這種情況,只有一個辦法:把記憶體加到比硬碟大。
2 手動釋放方法
2。1 使用free檢視一下當前記憶體使用情況(可略過):
[root@*** ~]# free -m
total used free shared buffers cached
Mem:
512 488 23 0 57 157
-/+ buffers/cache: 273 238 Swap:
1055 0 10552。2
執行sync同步資料
[root@*** ~]# sync2。3 清理cache
[root@*** ~]#echo 3 > /proc/sys/vm/drop_caches2。4 drop_cache的詳細文件如下,以便查閱
Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free。
To free pagecache:
* echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
* echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
* echo 3 > /proc/sys/vm/drop_caches
As this is a non-destructive operation, and dirty objects are notfreeable, the user should run “sync” first in order to make sure allcached objects are freed。
This tunable was added in 2。6。16。
回答pagein的問題
應該是因為檔案頁面不像匿名頁做remap而是直接丟掉重新讀
具體可見 compact_zone->migrate_pages
解決 另外把預讀大一點連續點減少點碎頁?
我覺得核心還是記憶體不能滿足你的業務需求 雖然可調整招還不少 不過那麼辛苦折騰不如加點記憶體來的省力不容易出問題啊
最後再多說幾句 這幾年IO的節省挺重要的 而去年mapping->a_ops->migratepage的介面已經就位(現在主要使用者是zsmalloc) 是不是可以給file cache增加migrate的來節省IO是一個不錯的點子?