linux 記憶體佔用過大分析__linux

來源:互聯網
上載者:User

1、使用 free -g 查看記憶體使用量情況:


2、查看進程佔用的記憶體情況:

ps aux|awk '{sum+=$6} END {print sum/1024}'

結果發現佔用了 17G


3、查看記憶體配置情況:
cat /proc/meminfo
 
 
 
那slab是什麼呢。 

slab是Linux作業系統的一種記憶體配置機制。其工作是針對一些經常分配並釋放的對象,如進程描述符等,這些對象的大小一般比較小,如果直接採用夥伴系統來進行分配和釋放,不僅會造成大量的內片段,而且處理速度也太慢。而slab分配器是基於對象進行管理的,相同類型的對象歸為一類(如進程描述符就是一類),每當要申請這樣一個對象,slab分配器就從一個slab列表中分配一個這樣大小的單元出去,而當要釋放時,將其重新儲存在該列表中,而不是直接返回給夥伴系統,從而避免這些內片段。slab分配器並不丟棄已指派的對象,而是釋放並把它們儲存在記憶體中。當以後又要請求新的對象時,就可以從記憶體直接擷取而不用重複初始化。

具體為:

採用夥伴演算法分配記憶體時,每次至少分配一個頁面。但當請求分配的記憶體大小為幾十個位元組或幾百個位元組時應該如何處理。如何在一個頁面中分配小的記憶體區,小記憶體區的分配所產生的內片段又如何解決。

Linux2.0採用的解決辦法是建立了13個空閑區鏈表,它們的大小從32位元組到132056位元組。從Linux2.2開始,MM的開發人員採用了一種叫做slab的分配模式,該模式早在1994年就被開發出來,用於Sun Microsystem Solaris 2.4作業系統中。Slab的提出主要是基於以下考慮:

1) 核心對記憶體區的分配取決於所存放資料的類型。例如,當給使用者態進程分配頁面時,核心調用get free page()函數,並用0填充這個頁面。 而給核心的資料結構分配頁面時,事情沒有這麼簡單,例如,要對資料結構所在的記憶體進行初始化、在不用時要收回它們所佔用的記憶體。因此,Slab中引入了對象這個概念,所謂對象就是存放一組資料結構的記憶體區,其方法就是構造或解構函式,建構函式用於初始化資料結構所在的記憶體區,而解構函式收回相應的記憶體區。但為了便於理解,你也可以把對象直接看作核心的資料結構。為了避免重複初始化對象,Slab分配模式並不丟棄已指派的對象,而是釋放但把它們依然保留在記憶體中。當以後又要請求分配同一對象時,就可以從記憶體擷取而不用進行初始化,這是在Solaris 中引入Slab的基本思想。

實際上,Linux中對Slab分配模式有所改進,它對記憶體區的處理並不需要進行初始化或回收。出於效率的考慮,Linux並不調用對象的構造或解構函式,而是把指向這兩個函數的指標都置為空白。Linux中引入Slab的主要目的是為了減少對夥伴演算法的調用次數。

2) 實際上,核心經常反覆使用某一記憶體區。例如,只要核心建立一個新的進程,就要為該進程相關的資料結構(task_struct、開啟檔案對象等)分配記憶體區。當進程結束時,收回這些記憶體區。因為進程的建立和撤銷非常頻繁,因此,Linux的早期版本把大量的時間花費在反覆分配或回收這些記憶體區上。從Linux2.2開始,把那些頻繁使用的頁面儲存在快取中並重新使用。

3) 可以根據對記憶體區的使用頻率來對它分類。對於預期頻繁使用的記憶體區,可以建立一組特定大小的專用緩衝區進行處理,以避免內片段的產生。對於較少使用的記憶體區,可以建立一組通用緩衝區(如Linux2.0中所使用的2的冪次方)來處理,即使這種處理模式產生片段,也對整個系統的效能影響不大。

4) 硬體快取的使用,又為盡量減少對夥伴演算法的調用提供了另一個理由,因為對夥伴演算法的每次調用都會“弄髒”硬體快取,因此,這就增加了對記憶體的平均訪問次數。

Slab分配模式把對象分組放進緩衝區(儘管英文中使用了Cache這個詞,但實際上指的是記憶體中的地區,而不是指硬體快取)。因為緩衝區的組織和管理與硬體快取的命中率密切相關,因此,Slab緩衝區並非由各個對象直接構成,而是由一連串的“大塊(Slab)”構成,而每個大塊中則包含了若干個同種類型的對象,這些對象或已被分配,或空閑,如圖6.12所示。一般而言,對象分兩種,一種是大對象,一種是小對象。所謂小對象,是指在一個頁面中可以容納下好幾個對象的那種。例如,一個inode結構大約佔300多個位元組,因此,一個頁面中可以容納8個以上的inode結構,因此,inode結構就為小對象。Linux核心中把小於512位元組的對象叫做小對象。實際上,緩衝區就是主存中的一片地區,把這片地區劃分為多個塊,每塊就是一個Slab,每個Slab由一個或多個頁面組成,每個Slab中存放的就是對象。

2,通過slabtop命令查看slab緩衝資訊

通過slabtop我們看到Linux系統中有大量的dentry cache佔用記憶體,那dentry cache是什麼呢。

首先,我們知道inode對應於物理磁碟上的具體對象,而dentry是一個記憶體實體,其中的d inode成員指向對應的inode,故可以把dentry看成是Linux檔案系統中某個索引節點(inode)的連結,這個索引節點可以是檔案,也可以是目錄。而dentry cache是目錄項快取,是Linux為了提高目錄項對象的處理效率而設計的,它記錄了目錄項到inode的映射關係。

3,結合storm服務分析

當前伺服器是storm叢集的節點,首先想到了storm相關的背景工作處理序,strace一下storm的worker進程發現其中有非常頻繁的stat系統調用發生,而且stat的檔案總是新的檔案名稱:

[@storm-yd8325 ~]# strace -fp 31984 -e trace=stat

進一步觀察到storm的worker進程會在本地目錄下頻繁的建立、開啟、關閉、刪除心跳檔案,每秒鐘一個新的檔案名稱:

[@storm-yd8325 ~]# sudo strace -fp 31984 -e trace=open,stat,close,unlink

總結:storm進程頻繁的檔案io操作,導致了dentry_cache佔用了系統太多的記憶體資源。

4,系統的自動slab緩衝回收

在slab緩衝中,對象分為SReclaimable(可回收)和SUnreclaim(不可回收),而在系統中絕大多數對象都是可回收的。核心有一個參數,當系統記憶體使用量到一定量的時候,會自動觸動回收操作。核心參數:

vm.min_free_kbytes = 836787

1)代表系統所保留空閑記憶體的最低限。

在系統初始化時會根據記憶體大小計算一個預設值,計算規則是:

min_free_kbytes = sqrt(lowmem_kbytes * 16) = 4 * sqrt(lowmem_kbytes)(註:lowmem_kbytes即可認為是系統記憶體大小)

另外,計算出來的值有最小最大限制,最小為128K,最大為64M。

可以看出,min free kbytes隨著系統記憶體的增大不是線性增長,因為隨著記憶體的增大,沒有必要也線性預留出過多的記憶體,能保證緊急時刻的使用量便足矣。

2)min free kbytes的主要用途是計算影響記憶體回收的三個參數 watermark[min/low/high]

(1) watermark[high] > watermark [low] > watermark[min],各個zone各一套

(2)在系統空閑記憶體低於 watermark[low]時,開始啟動核心線程kswapd進行記憶體回收(每個zone一個),直到該zone的空閑記憶體數量達到watermark[high]後停止回收。如果上層申請記憶體的速度太快,導致空閑記憶體降至watermark[min]後,核心就會進行direct reclaim(直接回收),即直接在應用程式的進程上下文中進行回收,再用回收上來的空閑頁滿足記憶體申請,因此實際會阻塞應用程式,帶來一定的響應延遲,而且可能會觸發系統OOM。這是因為watermark[min]以下的記憶體屬於系統的自留記憶體,用以滿足特殊使用,所以不會給使用者態的普通申請來用。

(3)三個watermark的計算方法:

watermark[min] = min free kbytes換算為page單位即可,假設為min free pages。(因為是每個zone各有一套watermark參數,實際計算效果是根據各個zone大小所佔記憶體總大小的比例,而算出來的per zone min free pages)

 watermark[low] = watermark[min] * 5 / 4 watermark[high] = watermark[min] * 3 / 2

所以中間的buffer量為 high - low = low - min = per_zone_min_free_pages * 1/4 。因為 min_free_kbytes = 4* sqrt(lowmem_kbytes) ,也可以看出中間的buffer量也是跟記憶體的增長速度成開方關係。

(4)可以通過/proc/zoneinfo查看每個zone的watermark

例如:

Node 0, zone      DMApages free     3960       min      65       low      81       high     97

3)min free kbytes大小的影響

min_free_kbytes 設的越大,watermark的線越高,同時三個線之間的buffer量也相應會增加。這意味著會較早的啟動kswapd進行回收,且會回收上來較多的記憶體(直至watermark[high]才會停止),這會使得系統預留過多的空閑記憶體,從而在一定程度上降低了應用程式可使用的記憶體量。極端情況下設定 min_free_kbytes 接近記憶體大小時,留給應用程式的記憶體就會太少而可能會頻繁地導致OOM的發生。

min_free_kbytes 設的過小,則會導致系統預留記憶體過小。kswapd回收的過程中也會有少量的記憶體配置行為(會設上PF_MEMALLOC)標誌,這個標誌會允許kswapd使用預留記憶體;另外一種情況是被OOM選中殺死的進程在退出過程中,如果需要申請記憶體也可以使用預留部分。這兩種情況下讓他們使用預留記憶體可以避免系統進入deadlock狀態。

5,最終結果

最終查明, slab cache 佔用過多屬於正常問題,並且當記憶體到達系統最低空閑記憶體限制的話,會自動觸發kswapd進程來回收記憶體,屬於正常現象。

註:測了一下,當調整完min free kbytes值大於系統空閑記憶體後,kswapd進程的確從休眠狀態進入運行態,開始回收記憶體。

根據我們跑的storm服務做出如下調整:

vm.vfs_cache_pressure = 200

該檔案表示核心回收用於directory和inode cache記憶體的傾向;預設值100表示核心將根據pagecache和swapcache,把directory和inode cache保持在一個合理的百分比;降低該值低於100,將導致核心傾向於保留directory和inode cache;增加該值超過100,將導致核心傾向於回收directory和inode cache。

 


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.