經典博客
類型 | 文章 |
---|---|
slab、slub的關係 | SLUB和SLAB的區別 |
系統性介紹kernel內存泄漏檢測 | Linux內存管理 (22)內存檢測技術、Linux內存使用情況以及內存泄露分析之工具與方法 |
drop_cache應用 | liunx的Slab佔用比較高的問題 |
slub、slab內存泄漏診斷有區別 | https://blog.csdn.net/dolp怎樣診斷SLAB泄露問題 |
判斷slub、slab是否內存泄漏 | linux通過meminfo 與 slab 定位內存泄漏 |
實例 | 認識Kernel 內存泄漏、slub泄露分析 |
工具介紹與使用 | kmemleak的使用 |
觸發slab回收
博文: https://www.iteye.com/blog/fengbin2005-2218722
上文排查到Linux系統中有大量的dentry_cache佔用內存,爲什麼會有如此多的dentry_cache呢?
-
首先,弄清楚dentry_cache的概念及作用:目錄項高速緩存,是Linux爲了提高目錄項對象的處理效率而設計的;它記錄了目錄項到inode的映射關係。因此,當應用程序發起stat系統調用時,就會創建對應的dentry_cache項(更進一步,如果每次stat的文件都是不存在的文件,那麼總是會有大量新的dentry_cache項被創建)。
-
當前服務器是storm集羣的節點,首先想到了storm相關的工作進程,strace一下storm的worker進程發現其中有非常頻繁的stat系統調用發生,而且stat的文件總是新的文件名:
sudo strace -fp <pid> -e trace=stat
-
進一步觀察到storm的worker進程會在本地目錄下頻繁的創建、打開、關閉、刪除心跳文件,每秒鐘一個新的文件名:
sudo strace -fp <pid> -e trace=open,stat,close,unlink
以上就是系統中爲何有如此多的dentry_cache的原因所在。
一個奇怪的現象
通過觀察/proc/meminfo發現,slab內存分爲兩部分:
SReclaimable // 可回收的slab
SUnreclaim // 不可回收的slab
當時服務器的現狀是:slab部分佔用的內存,大部分顯示的都是SReclaimable,也就是說可以被回收的。
但是通過slabtop觀察到slab內存中最主要的部分(dentry_cache)的OBJS幾乎都是ACTIVE的,顯示100%處於被使用狀態。
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
13926348 13926348 100% 0.21K 773686 18 3494744K dentry_cache
334040 262056 78% 0.09K 8351 40 33404K buffer_head
151040 150537 99% 0.74K 30208 5 120832K ext3_inode_cache
爲什麼顯示可回收的,但是又處於ACTIVE狀態呢?求Linux內核達人看到後熱心解釋下:
會不會由於是ACTIVE狀態,導致dcache沒有被自動回收釋放掉呢?
讓系統自動回收dcache
上一小節,我們已經提到,服務器上大部分的slab內存是SReclaimable可回收狀態的,那麼,我們能不能交給操作系統讓他在某個時機自動觸發回收操作呢?答案是肯定的。
修改觸發回收cache
查了一些關於Linux dcache的相關資料,發現操作系統會在到了內存臨界閾值後,觸發kswapd內核進程工作才進行釋放,這個閾值的計算方法如下:
-
首先,grep low /proc/zoneinfo,得到如下結果:
low 1 low 380 low 12067
-
將以上3列加起來,乘以4KB,就是這個閾值,通過這個方法計算後發現當前服務器的回收閾值只有48MB,因此很難看到這一現象,實際中可能等不到回收,操作系統就會hang住沒響應了。
-
可以通過以下方法調大這個閾值:將vm.extra_free_kbytes設置爲vm.min_free_kbytes和一樣大,則/proc/zoneinfo中對應的low閾值就會增大一倍,同時high閾值也會隨之增長,以此類推。
$ sudo sysctl -a | grep free_kbytes vm.min_free_kbytes = 39847 vm.extra_free_kbytes = 0 ######1GB $ sudo sysctl -w vm.extra_free_kbytes=836787 ####系統中 沒有vm.extra_free_kbytes 這個參數,修改下面的參數 $ /sbin/sysctl -w vm.min_free_kbytes=836787
-
舉個例子,當low閾值被設置爲1GB的時候,當系統free的內存小於1GB時,觀察到kswapd進程開始工作(進程狀態從Sleeping變爲Running),同時dcache開始被系統回收,直到系統free的內存介於low閾值和high閾值之間,停止回收。