網站首頁 編程語言 正文
占用大量的File Cache,內存利用不充分導致swap
基本原則:盡量使用內存,減少swap,同時,盡早flush到外存,早點釋放內存給寫cache使用。---特別在持續的寫入操作中,此優化非常有效。 讀少寫多
調優措施:
vm.swapiness :60 改成 10
vm.dirty_ratio:90 改成 10
vm.dirty_background_ratio:60 改成 5
vm.dirty_expire_centisecs:3000改成500
vm.vfs_cache_pressure:100 改成 500
下面重點解釋一下各個配置的含義:
一,vm.swappiness優化:
swappiness的值的大小對如何使用swap分區是有著很大的聯系的。swappiness=0的時候表示最大限度使用物理內存,然后才是 swap空間,swappiness=100的時候表示積極的使用swap分區,并且把內存上的數據及時的搬運到swap空間里面。linux的基本默認設置為60,具體如下:
cat /proc/sys/vm/swappiness
60
也就是說,你的內存在使用到100-60=40%的時候,就開始出現有交換分區的使用。大家知道,內存的速度會比磁盤快很多,這樣子會加大系統io,同時造的成大量頁的換進換出,嚴重影響系統的性能,所以我們在操作系統層面,要盡可能使用內存,對該參數進行調整。
臨時調整的方法如下,我們調成10:
sysctl vm.swappiness=10
vm.swappiness = 10
cat /proc/sys/vm/swappiness
10
這只是臨時調整的方法,重啟后會回到默認設置的
要想永久調整的話,需要將在/etc/sysctl.conf修改,加上:
cat /etc/sysctl.conf
vm.swappiness=10
二,vm.dirty_ratio: 同步刷臟頁,會阻塞應用程序
這個參數控制文件系統的同步寫寫緩沖區的大小,單位是百分比,表示當寫緩沖使用到系統內存多少的時候(即指定了當文件系統緩存臟頁數量達到系統內存百分之多少時(如10%),),開始向磁盤寫出數據,即系統不得不開始處理緩存臟頁(因為此時臟頁數量已經比較多,為了避免數據丟失需要將一定臟頁刷入外存),在此過程中很多應用進程可能會因為系統轉而處理文件IO而阻塞。
增大之會使用更多系統內存用于磁盤寫緩沖,也可以極大提高系統的寫性能。但是,當你需要持續、恒定的寫入場合時,應該降低其數值,一般啟動上缺省是 10。
三,vm.dirty_background_ratio:異步刷臟頁,不會阻塞應用程序
這個參數控制文件系統的后臺進程,在何時刷新磁盤。單位是百分比,表示系統內存的百分比,意思是當寫緩沖使用到系統內存多少的時候,就會觸發pdflush/flush/kdmflush等后臺回寫進程運行,將一定緩存的臟頁異步地刷入外存。增大之會使用更多系統內存用于磁盤寫緩沖,也可以極大提高系統的寫性能。但是,當你需要持續、恒定的寫入場合時,應該降低其數值,一般啟動上缺省是 5。
注意:如果dirty_ratio設置比dirty_background_ratio大,可能認為dirty_ratio的觸發條件不可能達到,因為每次肯定會先達到vm.dirty_background_ratio的條件,然而,確實是先達到vm.dirty_background_ratio的條件然后觸發flush進程進行異步的回寫操作,但是這一過程中應用進程仍然可以進行寫操作,如果多個應用進程寫入的量大于flush進程刷出的量那自然會達到vm.dirty_ratio這個參數所設定的坎,此時操作系統會轉入同步地處理臟頁的過程,阻塞應用進程。
四,vm.dirty_expire_centisecs:
這個參數聲明Linux內核寫緩沖區里面的數據多“舊”了之后,pdflush進程就開始考慮寫到磁盤中去。單位是 1/100秒。缺省是 3000,也就是 30 秒的數據就算舊了,將會刷新磁盤。對于特別重載的寫操作來說,這個值適當縮小也是好的,但也不能縮小太多,因為縮小太多也會導致IO提高太快。建議設置為 1500,也就是15秒算舊。當然,如果你的系統內存比較大,并且寫入模式是間歇式的,并且每次寫入的數據不大(比如幾十M),那么這個值還是大些的好。
五,Vm.dirty_writeback_centisecs:
這個參數控制內核的臟數據刷新進程pdflush的運行間隔。單位是 1/100 秒。缺省數值是500,也就是 5 秒。如果你的系統是持續地寫入動作,那么實際上還是降低這個數值比較好,這樣可以把尖峰的寫操作削平成多次寫操作。設置方法如下:
echo "200" > /proc/sys/vm/dirty_writeback_centisecs
如果你的系統是短期地尖峰式的寫操作,并且寫入數據不大(幾十M/次)且內存有比較多富裕,那么應該增大此數值:
六,Vm.vfs_cache_pressure:
增大這個參數設置了虛擬內存回收directory和inode緩沖的傾向,這個值越大。越易回收
該文件表示內核回收用于directory和inode cache內存的傾向;缺省值100表示內核將根據pagecache和swapcache,把directory和inode cache保持在一個合理的百分比;降低該值低于100,將導致內核傾向于保留directory和inode cache;增加該值超過100,將導致內核傾向于回收directory和inode cache。
This variable controls the tendency of the kernel to reclaim thememory which is used for caching of VFS caches, versus pagecache and swap.Increasing this value increases the rate at which VFS caches are reclaimed.Itis difficult to know when this should be changed, other than byexperimentation. The slabtop command (part of the package procps) shows topmemory objects used by the kernel. The vfs caches are the "dentry"and the "*_inode_cache" objects. If these are consuming a largeamount of memory in relation to pagecache, it may be worth trying to increasepressure. Could also help to reduce swapping. The default value is 100.
?
同事說有一臺服務器的內存用光了,我連上去用free看了下,確實有點怪。
$ free -g total used free shared buffers cached Mem: 15 15 0 0 2 0 -/+ buffers/cache: 12 2 Swap: 17 0 17
正常情況
free -g
? ? ? ? ? ? ? total ? ? ? ?used ? ? ? ?free ? ? ?shared ?buff/cache ? available
Mem: ? ? ? ? ? ?251 ? ? ? ? 204 ? ? ? ? ? 3 ? ? ? ? ?23 ? ? ? ? ?43 ? ? ? ? ?18 --- 還有100多G分給了SGA
Swap: ? ? ? ? ? 127 ? ? ? ? ? 0 ? ? ? ? 127
這臺服務器有16G內存,但是結果顯示除了2G左右的文件Buffer緩存外,其余十幾G都被確確實實的用光了。(free按1024進制計算,總內存可能比實際偏小)
這里大概介紹下free結果的含義:
/ |
total |
used |
free |
shared |
buffers |
cached |
---|---|---|---|---|---|---|
Mem |
總物理內存 |
當前使用的內存(包括slab+buffers+cached) |
完全沒有使用的內存 |
進程間共享的內存 |
緩存文件的元數據[1] |
緩存文件的具體內容[1] |
-/+ buffers/cache |
當前使用的內存(不包括buffers+cached,但包括slab) |
未使用和緩存的內存(free+buffers+cached) |
||||
Swap |
總的交換空間 |
已使用的交換空間 |
未使用的交換空間 |
然后top看了下,沒有特別吃內存的程序。用ps大概統計下所有程序占用的總內存:
$ ps aux | awk '{mem += $6} END {print mem/1024/1024}' 第6個值是使用的內存,第5個是shared
0.595089
結果顯示所有進程占用的內存還不到1G,實際上,因為free, ps的統計方式的差別和Copy-on-write和Shared libraries等內存優化機制的存在,這兩者的統計結果通常是不一樣的。但是一般情況下絕對不會相差十幾個G,
肯定是有什么隱藏的問題,Google了許久后發現,free沒有專門統計另一項緩存: Slab。
Slab簡介和進一步調查
Slab Allocation是Linux 2.2之后引入的一個內存管理機制,專門用于緩存內核的數據對象,可以理解為一個內核專用的對象池,可以提高系統性能并減少內存碎片。(Linux 2.6.23之后,SLUB成為了默認的allocator。)
查看Slab緩存
$ cat /proc/meminfo
其中,Slab相關的數據為
Slab: 154212 kB SReclaimable: 87980 kB SUnreclaim: 66232 kB
SReclaimable(Linux 2.6.19+)都是clean的緩存,隨時可以釋放。回到之前的內存問題,我查了下那臺服務器上Slab占用的內存:
$ cat /proc/meminfo | grep Slab Slab: 12777668 kB
12G的Slab緩存,有意思的是free把Slab緩存統計到了used memory中,這就是之前那個問題的癥結所在了。
另外,還可以查看/proc/slabinfo
(或使用slabtop命令)來查看Slab緩存的具體使用情況。
結果發現,ext3_inode_cache和dentry_cache占用了絕大部分內存。
考慮到這臺服務器會頻繁地用rsync同步大量的文件,這個結果也并不意外。
解決問題
先說明一下,如果問題僅僅是Slab占用了太多的內存(SReclaimable),那么通常不需要太操心,因為這根本不是個問題(如果是SUnreclaim太多且不斷增長,那么很有可能是內核有bug)。但是,如果是因為Slab占用內存太多而引起了其他的問題,建議繼續閱讀。
清除Slab可回收緩存
通過/proc/sys/vm/drop_caches
這個配置項,我們可以手動清除指定的可回收緩存(SReclaimable)[2]。
echo 2 > /proc/sys/vm/drop_caches 表示清除回收slab分配器中的對象(包括目錄項緩存和inode緩存)。slab分配器是內核中管理內存的一種機制,其中很多緩存數據實現都是用的pagecache。
上面的命令會主動釋放Slab中clean的緩存(包括inode和dentry的緩存)
,然后再free -g
一下,未使用的內存陡增了十幾個G。。。
需要注意的是,手動清除緩存可能會在一段時間內降低系統性能。原則上不推薦這么做,因為如果有需要,系統會自動釋放出內存供其他程序使用。
另外,手動清除Slab緩存是一個治標不治本的辦法。
因為問題不在Slab,而在于我們那個會引起Slab緩存飆漲的進程(我這里應該是rsync)。實際操作的時候發現,清除緩存一段時間后,Slab緩存很快又會“反彈”回去。如果需要治本,要么搞定問題進程,要么修改系統配置。
調整系統vm配置
風險預警:?調整以下系統配置可能會對系統性能造成負面影響,請仔細測試并謹慎操作。
/etc/sysctl.conf
里有幾個對內存管理影響比較大的配置,以下配置項的文檔見vm.txt。
vm.vfs_cache_pressure
系統在進行內存回收時,會先回收page cache, inode cache, dentry cache和swap cache。vfs_cache_pressure越大,每次回收時,inode cache和dentry cache所占比例越大[3]。
vfs_cache_pressure默認是100,值越大inode cache和dentry cache的回收速度會越快,越小則回收越慢,為0的時候完全不回收(OOM!)。
linux io caches0%
圖片取自The Linux Kernel's VFS Layer
vm.min_free_kbytes
系統的"保留內存"的大小,"保留內存"用于低內存狀態下的"atomic memory allocation requests"(eg. kmalloc + GFP_ATOMIC),該參數也被用于計算開始內存回收的閥值,默認在開機的時候根據當前的內存計算所得,越大則表示系統會越早開始內存回收。
min_free_kbytes過大可能會導致OOM,太小可能會導致系統出現死鎖等問題。
vm.swappiness
該配置用于控制系統將內存swap out到交換空間的積極性,取值范圍是[0, 100]。swappiness越大,系統的交換積極性越高,默認是60,如果為0則不會進行交換。
參考資料
- man proc
- The Linux Kernel's VFS Layer
- The VFS in Linux Kernel V2.4
- openSUSE: System Analysis and Tuning Guide, Chapter 15. Tuning the Memory Management Subsystem
- Red Hat Enterprise Linux, 5.5 Tuning Virtual Memory
- Odd behavior
- Wikipedia:Slab allocation
原文鏈接:https://blog.csdn.net/jnrjian/article/details/126929725
- 上一篇:matplotlib自定義風格
- 下一篇:MP(MyBaitsPlus)代碼生成器
相關推薦
- 2023-03-04 linux服務器CPU飆高排查分析_Linux
- 2022-09-21 go?mod詳細使用教程_Golang
- 2023-06-18 Redis優雅地實現延遲隊列的方法分享_Redis
- 2023-02-07 go?reflect要不要傳指針原理詳解_Golang
- 2022-12-04 Jetpack之CameraX的使用_Android
- 2022-04-06 .NET?Core使用CZGL.SystemInfo庫獲取主機運行資源_基礎應用
- 2022-06-07 Docker的四種網絡模式_docker
- 2022-07-28 Redis基本數據類型哈希Hash常用操作命令_Redis
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支