您好,登錄后才能下訂單哦!
這篇文章主要介紹Linux物理內存外碎片的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
什么是Linux物理內存碎片化?Linux物理內存碎片化包括兩種:
物理內存內碎片:指分配給用戶的內存空間中未被使用的部分
例如進程需要使用3K bytes物理內存,于是向系統申請了大小等于3Kbytes的內存,但是由于Linux內核伙伴系統算法最小顆粒是4K bytes,所以分配的是4Kbytes內存,那么其中1K bytes未被使用的內存就是內存內碎片。
物理內存外碎片化:指系統中無法利用的小內存塊
例如系統剩余內存為16K bytes,但是這16K bytes內存是由4個4K bytes的頁面組成,即16K內存物理頁幀號#1不連續。在系統剩余16K bytes內存的情況下,系統卻無法成功分配大于4K的連續物理內存,該情況就是內存外碎片導致,本文中闡述的就是物理內存外碎片化。
注:#1物理頁幀號:Linux物理內存是通過頁面進行管理,并對每個頁面進行編號,稱為頁幀號,如果是連續的兩個物理頁面,其頁幀號是連續的。
闡述物理內存外碎片化的來龍去脈前,先得明白Linux是如何管理物理內存的?Linux內核采用的是buddy system allocation,即著名的伙伴系統分配器。
設計思路
伙伴系統分配器的核心思路:將系統的空閑頁面分為11個塊鏈表,每個塊鏈表分別管理著1,2,4,8,16,32,64,128,256,512和1024個物理頁幀號連續的頁面。每個頁面大小為4K bytes,buddy管理的塊大小范圍從4K bytes到4M bytes,以2的倍數遞增。
管理邏輯
Linux對物理頁面管理的框架如上圖,由于本文闡述的是物理內存外碎片,所以關于伙伴系統本文只做簡單分析,不涉及具體的細節并不闡述關于per cpu pageset等內容,如果讀者有興趣,可以參考內核源碼。
Linux將物理內存分為不同的node和zone來管理:
zone管理單元下的內存通過free_area數組將內存分成11個塊鏈表進行管理:
以此類推;
free_area管理的內存還細分為各種類型,例如不可移動頁面和可移動頁面等,每種類型的頁面類型對應一個free_list鏈表,該鏈表就鏈接著頁面結構體。
當向伙伴系統釋放頁面時,buddy釋放頁面的步驟如下:
從“二、Linux物理內存管理架構”,可以發現伙伴系統內存管理框架是可以有效改善物理內存外碎片的,因為伙伴系統有如下兩個管理邏輯,可以減少了外碎片化的產生:
除此之外,內核還支持以下措施改善物理內存外碎片化(只列舉主要的機制):
memory compaction
(1)內存規整原理
Linux物理頁面規整機制,類似于磁盤整理,主要是應用了內核的頁面遷移機制,是一種將可移動頁面進行遷移后騰出連續物理內存的方法。
假設存在一個非常小的內存域如下:
藍色表示空閑的頁面,白色表示已經被分配的頁面,可以看到如上內存域的空閑頁面(藍色)非常零散,無法分配大于兩頁的連續物理內存。
下面演示一下內存規整的簡化工作原理,內核會運行兩個獨立的掃描動作:第一個掃描從內存域的底部開始,一邊掃描一邊將已分配的可移動(MOVABLE)頁面記錄到一個列表中:
另外第二掃描是從內存域的頂部開始,掃描可以作為頁面遷移目標的空閑頁面位置,然后也記錄到一個列表里面:
等兩個掃描在域中間相遇,意味著掃描結束,然后將左邊掃描得到的已分配的頁面遷移到右邊空閑的頁面中,左邊就形成了一段連續的物理內存,完成頁面規整。
(2)使用方法
如果想打開內存規整,內核需要打開相關的配置(默認為y)
打開如上配置后,內存規整的觸發是自動的,觸發內存規整的途徑如下:當進程嘗試分配高階內存無法滿足并且完成direct_reclaim#1(暫不分析costly_order情況)后,系統會根據內存剩余判斷是否觸發內存規整;
注:#1direct_reclaim:進程分配內存時發現內存不足從而啟動直接回收內存操作,這種模式下分配和回收是同步的關系,也就是說分配內存的進程會因為等待內存回收而被阻塞。
內核也提供了接口給用戶觸發規整動作,接口如下:
/proc/sys/vm/compact_memory
只要往這個節點寫值即可觸發對系統所有node管理的內存做內存規整。
kcompactd
(1)kcompact設計原理
kcompactd是一個內核規整的后臺進程,它跟memory compaction的區別在于:
memory compaction的觸發途徑是內存分配進入direct_reclaim(暫不分析costly_order情況)后系統會根據內存剩余判斷是否觸發內存規整,或者用戶手動觸發;
kcompactd在喚醒kswapd或者kswapd進入休眠時,主動觸發內存規整。
kcompactd的觸發路徑如下:主要有如下兩個途徑:
喚醒kswapd之前觸發規整,觸發的條件是:本次分配不支持direct_reclaim,node內存節點是平衡的,并且kswapd失敗的次數大于MAX_RECLAIM_RETRIES(默認16)。
kswapd即將進入睡眠時:
(2)使用方法
如果想打開內存規整,內核需要打開相關的配置(默認為y)
其他優化的思路
內核經過不斷的優化,那為何Linux為何還有物理內存外碎片化呢?那是因為物理內存外碎片化雖然是可以不斷優化的,但卻無法得到根除。目前的內核,我覺得導致物理外碎片化還有以下兩個主要原因:
不可移動頁面污染了內存環境,導致頁面規整失敗;
隨著系統不斷申請和釋放的頁面,導致伙伴系統分配的物理內存頁幀號越發隨機,從而導致內存被隔斷的概率越高,碎片化的程度越高,在3.2闡述。
針對以上兩個原因,以下的優化措施可能達到一定的優化效果:
(1)減少UNMOVABLE頁面污染內存環境
Linux內存分配中支持fallback機制,又叫偷頁機制。該機制是為了規避同個zone管理單位頁面類型剩余不平衡的問題,例如同個zone,A頁面類型空閑內存較多,B頁面類型空閑內存卻非常緊缺,如果沒有偷頁機制,分配B頁面類型就會進入內存分配慢速路徑。有了偷頁機制,在同個zone管理單位,如果UNMOVABLE類型無空閑頁面,但是MOVABLE類型頁面還有空閑頁面,偷頁機制支持在list_head[UNMOVABLE]分配不到頁面的情況下,向list_head[MOVABLE]分配頁面。
以下數組明確了各種頁面類型可偷的頁面類型,例如第一行表示UNMOVABLE頁面可以偷RECLAIMABLE和MOVABLE類型的頁面,其他類似。
如果不可移動頁面頻繁的偷頁會導致不可移動頁面很快污染了內存環境,特別污染了可移動頁面的內存,對內存規整成功率的影響比較大。基于以上情況,可以在偷頁的機制上加上分配大小限制的判斷,不可移動頁面只有大塊內存分配才允許偷頁,以此減少不可移動頁面對內存環境的污染。
不可移動類型頁面偷頁后主動償還
該方法主要是不可移動頁面偷頁后的一種補償方法。如果發生不可移動頁面偷頁后,我們將該頁面記錄到一個列表,等后續不可移動頁面類型存在空閑頁面時,將所偷的頁面遷移回不可移動頁面中,從而降低不可移動頁面的污染。
(2)降低分配頁幀號的隨機性
假設有一塊小內存域如下,以下兩種內存分配方式哪種會導致嚴重的內存碎片化?
明顯是第二種內存分配方式的對內存外碎片化更不友好,而這點也是伙伴系統目前沒有解決的問題。伙伴系統雖然將內存規劃成各種大小的內存塊,以讓小內存分配在小塊鏈表分配,盡量不污染大塊內存鏈表,但是卻沒辦法保證小塊內存具體是在物理內存的哪個頁幀范圍分配。隨著系統的運行越久,小塊內存的分配的物理頁幀號越發隨機,那么其導致碎片化的概率就會越高。
根據這種情況,可以通過預留的方式進行相應的優化。
預留一定的內存專門用于小塊內存分配,經過這個優化措施后,可以有效降低小塊內存分配的物理頁幀號的隨機性,從而降低小塊內存污染內存環境的概率。
預留一定的內存專門用于大塊內存分配,經過該優化措施后,預留的內存被小塊內存污染的概率就會降低,可以提升預留內存分配大塊內存的成功率。
以上是“Linux物理內存外碎片的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。