LWN:正式建立內(nèi)存策略zone!
關(guān)注了就能看到更多這么棒的文章哦~
Formalizing policy zones for memory
By Jonathan Corbet
March 5, 2024
Kimi Chat (https://kimi.moonshot.cn/) translation
https://lwn.net/Articles/964239/
內(nèi)核的內(nèi)存管理子系統(tǒng)是建立在“區(qū)域”(zones)概念之上的,這些區(qū)域最初被添加是為了描述其中包含的內(nèi)存頁的物理特性。隨著時間的推移,區(qū)域也承擔(dān)了更多的策略相關(guān)角色。通過一套名為 THP 分配器優(yōu)化(鏈接 1)的補(bǔ)丁集,Yu Zhao 開始更好地定義 policy 相關(guān)區(qū)域的角色,目的是為了增加兩個新的區(qū)域,終極目標(biāo)是改善內(nèi)核對透明巨頁(Transparent Huge Pages,THPs)的支持。
歷史上的 zone
一些背景知識可能有助于了解這一系列補(bǔ)丁的上下文。
最早的運(yùn)行 Linux 的 x86 系統(tǒng)通過 ISA 總線與外圍設(shè)備通信,該總線只能使用 24 位地址尋址 16MB 內(nèi)存。即使在那些日子里,計算機(jī)通常擁有的內(nèi)存也超過了這個數(shù)量,這意味著 ISA 設(shè)備無法用于 DMA I/O 操作的一些內(nèi)存無法使用。這使得任何可能在內(nèi)存中分配 DMA 緩沖區(qū)的設(shè)備驅(qū)動程序的作者生活變得不便。
為了避免這個問題,內(nèi)核在 1994 年 11 月的 1.1.68 版本中添加了 `GFP_DMA` 分配標(biāo)志。直到 1.1.69 版本,這個標(biāo)志實際上并沒有做任何事情,并且在 1.1.73 版本中,Buslogic SCSI 驅(qū)動程序添加了支持。這個標(biāo)志要求內(nèi)存管理子系統(tǒng)在 ISA 設(shè)備能夠到達(dá)的物理地址范圍內(nèi)分配內(nèi)存,這樣驅(qū)動程序作者在分配緩沖區(qū)時就不再需要擔(dān)心。
當(dāng)時,`GFP_DMA` 只是讓分配器跳過不適當(dāng)位置的內(nèi)存。這樣做是有效的,但生活,正如它的習(xí)慣一樣,變得更加復(fù)雜。內(nèi)核在早期只能管理不到 1GB 的物理內(nèi)存;由內(nèi)核劃分的 32 位地址空間,簡單地說,不能再包含更多。當(dāng)然,那近 1GB 的內(nèi)存應(yīng)該對任何人來說都足夠了。但用戶在使用他們?yōu)橹顿M(fèi)的所有內(nèi)存方面可能會相當(dāng)強(qiáng)烈,因此內(nèi)核開發(fā)者面臨找到解決方案的壓力。
解決方案是“高內(nèi)存”(high memory),它可以分配給用戶進(jìn)程,但在沒有明確的(和臨時的)映射步驟的情況下,不能被內(nèi)核直接尋址。高內(nèi)存在 1999 年末的 2.3.23pre3 版本中添加,增加了另一種必須考慮的內(nèi)存類型;內(nèi)核使用的內(nèi)存通常不能放在那里。當(dāng)時,有三種區(qū)域:`ZONE_DMA`、`ZONE_NORMAL` 和 `ZONE_HIGHMEM`。
區(qū)域系統(tǒng)的一個重要方面是,區(qū)域是按照允許簡單回退機(jī)制的順序組織的。任何可以從 `ZONE_HIGHMEM` 服務(wù)的分配也可以從其他兩個區(qū)域中的任何一個得到滿足,而且 `ZONE_NORMAL` 分配可以回退到 `ZONE_DMA`。這個屬性在當(dāng)前內(nèi)核中仍然存在。
2006 年 1 月發(fā)布的 2.6.15 內(nèi)核,在 `ZONE_DMA` 和 `ZONE_NORMAL` 之間添加了 `ZONE_DMA32`,以滿足只能處理 32 位 DMA 地址的設(shè)備的需求。在 2.6.23(2007 年 10 月)中添加了 `ZONE_MOVABLE`,在 4.3(2015 年 11 月)中添加了 `ZONE_DEVICE` 來描述安裝在外圍設(shè)備上的 CPU 可尋址內(nèi)存。
在一定程度上,所有這些區(qū)域都描述了涉及的內(nèi)存的物理特性,主要與可尋址性有關(guān)。`ZONE_MOVABLE` 是個例外。它描述了內(nèi)存,如果幸運(yùn)的話,所有內(nèi)容都可以在需要時移動到其他地方。例如,用戶空間頁面可以在內(nèi)存中的其他地方遷移;頁表條目將相應(yīng)更新,用戶空間永遠(yuǎn)不會知道有任何變化。這個區(qū)域是為了支持熱插拔內(nèi)存而添加的,這種內(nèi)存可以隨時添加到(或從)系統(tǒng)中。如果系統(tǒng)要從中移除內(nèi)存,首先將所有內(nèi)存內(nèi)容轉(zhuǎn)移到其他地方是相當(dāng)重要的。
熱插拔用例仍然存在,但 `ZONE_MOVABLE` 已經(jīng)成為內(nèi)存管理政策的一種表達(dá)。如果所有可移動頁面都放在內(nèi)存的同一區(qū)域,那么重新分配一些內(nèi)存來創(chuàng)建大的、物理上連續(xù)的范圍就相對容易了。所以現(xiàn)在 `ZONE_MOVABLE` 被用作分隔可移動和不可移動分配的方式,并為其他事物提供了重要支持,包括連續(xù)內(nèi)存分配器(contiguous memory allocator, 鏈接 2)。這里的重要點是 `ZONE_MOVABLE` 可以放置在物理內(nèi)存的任何位置;它不是由該內(nèi)存的物理特性驅(qū)動的,尤其是在大多數(shù)不使用熱插拔的系統(tǒng)上。
在當(dāng)前內(nèi)核中,區(qū)域?qū)哟谓Y(jié)構(gòu)是:
-
`ZONE_DMA`
-
`ZONE_DMA32`
-
`ZONE_NORMAL`
-
`ZONE_HIGHMEM`
-
`ZONE_MOVABLE`
-
`ZONE_DEVICE`
注意,不是所有系統(tǒng)都有所有區(qū)域;例如,當(dāng)前的 64 位系統(tǒng)不需要 `ZONE_HIGHMEM`。
明確的策略區(qū)域
趙認(rèn)為,內(nèi)存區(qū)域在輔助分配策略方面可以做得更多。具體來說,他認(rèn)為可能需要幾個其他策略區(qū)域(在代碼本身中通常稱為“虛擬區(qū)域”)。為此,他的補(bǔ)丁系列添加了:
-
`ZONE_NOSPLIT`,這是一個區(qū)域,其中連續(xù)的頁塊不能分割到給定大小以下。它的存在是為了幫助系統(tǒng)維護(hù)大塊內(nèi)存(用于透明大頁等),而無需經(jīng)歷持續(xù)的壓縮過程。
-
`ZONE_NOMERGE` 也具有最小塊大小屬性,但還禁止將頁塊合并成更大的組;因此,它只能容納單一大小的塊。
這些區(qū)域放置在 `ZONE_MOVABLE` 之后,保持了回退層次結(jié)構(gòu):`ZONE_NOMERGE` 分配也可以從 `ZONE_NOSPLIT` 得到滿足,或者如果失敗,可以從更低的區(qū)域得到滿足。這些區(qū)域的分配必須是可移動的,因此也可以回退到 `ZONE_MOVABLE`。
這些區(qū)域背后的思想是使透明大頁的分配盡可能高效。它們將防止大頁的分割,這將使內(nèi)核無需經(jīng)歷重新組裝它們的努力。目前進(jìn)行的壓縮工作的大部分可能會變得不必要。
從某種意義上說,這項工作可以被視為那些希望看到 Linux 總體上使用更大頁面大小的人和那些擔(dān)心相關(guān)內(nèi)部碎片成本的人之間的一種妥協(xié)。`ZONE_NOMERGE` 為內(nèi)核創(chuàng)建了接近第二種原生頁面大小的東西,在它們有意義的情況下提供更大的頁面,同時仍然保持較小頁面的可用性。
然而,透明大頁仍然可能存在內(nèi)部碎片問題;一個進(jìn)程可能分配了這樣一個頁面,但只使用了其中一小部分內(nèi)存。當(dāng)前內(nèi)核將嘗試通過將大頁拆回基礎(chǔ)頁面來應(yīng)對這種情況,允許未使用的部分在其他地方重新分配。
在(或以上)`ZONE_NOSPLIT` 中的頁面顯然不能拆分;這正是該區(qū)域存在要執(zhí)行的策略。相反,趙的補(bǔ)丁集引入了“粉碎”大頁的概念。如果一個頁面被粉碎,其內(nèi)容將被遷移(復(fù)制)到位于合適區(qū)域的較小頁面中;一旦該過程完成,原始的大頁(保持完整)可以分配給其他用途。粉碎比拆分更昂貴;趙認(rèn)為這是對于一個沒有正確使用其內(nèi)存的進(jìn)程的適當(dāng)成本;從變更日志(鏈接 3)中:“用零售術(shù)語來說,購買退貨會被收取重新上架費(fèi),原始商品可以重新銷售”。
`ZONE_NOMERGE` 的另一個聲稱的優(yōu)勢是,它促進(jìn)了巨大 vmemmap 優(yōu)化(HVO)(鏈接 4),這在 2020 年這里(鏈接 5)被涵蓋。簡而言之,這個技巧允許內(nèi)核回收用于保存大頁中許多頁面的 `page` 結(jié)構(gòu)的內(nèi)存。在大量使用大頁的系統(tǒng)中,這種優(yōu)化可以節(jié)省大量內(nèi)存。在當(dāng)前內(nèi)核中,HVO 只能與 hugetlbfs 機(jī)制一起使用,這種機(jī)制不透明,通常只用于特殊情況。然而,`ZONE_NOMERGE` 頁面像 hugetlbfs 頁面一樣組織在固定塊中,因此使用 HVO 變得容易。
補(bǔ)丁集處于早期階段;除其他事項外,它沒有任何基準(zhǔn)測試結(jié)果來顯示這種新機(jī)制的優(yōu)勢。其他開發(fā)者的審查評論才剛剛開始到來;這是一大塊工作,需要一些時間來消化。它可能會成為 5 月份的 Linux 存儲、文件系統(tǒng)、內(nèi)存管理和 BPF 峰會(鏈接 6)的討論話題。因此,這些新區(qū)域可能不會在不久的將來登陸內(nèi)核,但它們的優(yōu)勢在長期內(nèi)可能會證明是有說服力的。
[1]: https://lwn.net/ml/linux-mm/[email protected]/
[2]: https://lwn.net/Articles/486301/
[3]: https://lwn.net/ml/linux-mm/[email protected]/
[4]: https://www.kernel.org/doc/html/next/mm/vmemmap_dedup.html
[5]: https://lwn.net/Articles/839737/
[6]: https://events.linuxfoundation.org/lsfmmbpf/
全文完
LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。
長按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~
