您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關為什么Linux默認頁大小是 4KB,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
為什么這么設計(Why’s THE Design)是一系列關于計算機領域中程序設計決策的文章,我們在這個系列的每一篇文章中都會提出一個具體的問題并從不同的角度討論這種設計的優缺點、對具體實現造成的影響。如果你有想要了解的問題,可以在文章下面留言。
我們都知道 Linux 會以頁為單位管理內存,無論是將磁盤中的數據加載到內存中,還是將內存中的數據寫回磁盤,操作系統都會以頁面為單位進行操作,哪怕我們只向磁盤中寫入一個字節的數據,我們也需要將整個頁面中的全部數據刷入磁盤中。
Linux 同時支持正常大小的內存頁和大內存頁(Huge Page)[^1],絕大多數處理器上的內存頁的默認大小都是 4KB,雖然部分處理器會使用 8KB、16KB 或者 64KB 作為默認的頁面大小,但是 4KB 的頁面仍然是操作系統默認內存頁配置的主流;除了正常的內存頁大小之外,不同的處理器上也包含不同大小的大頁面,我們在 x86 處理器上就可以使用 2MB 的內存頁。
4KB 的內存頁其實是一個歷史遺留問題,在上個世紀 80 年代確定的 4KB 一直保留到了今天。雖然今天的硬件比過去豐富了很多,但是我們仍然沿用了過去主流的內存頁大小。如下圖所示,裝過機的人應該對這里的內存條非常熟悉:
圖 1 - 隨機存取內存
在今天,4KB 的內存頁大小可能不是最佳的選擇,8KB 或者 16KB 說不定是更好的選擇,但是這是過去在特定場景下做出的權衡。我們在這篇文章中不要過于糾結于 4KB 這個數字,應該更重視決定這個結果的幾個因素,這樣當我們在遇到類似場景時才可以從這些方面考慮當下最佳的選擇,我們在這篇文章中會介紹以下兩個影響內存頁大小的因素,它們分別是:
過小的頁面大小會帶來較大的頁表項增加尋址時 TLB(Translation lookaside buffer)的查找速度和額外開銷;
過大的頁面大小會浪費內存空間,造成內存碎片,降低內存的利用率;
上個世紀在設計內存頁大小時充分考慮了上述的兩個因素,最終選擇了 4KB 的內存頁作為操作系統最常見的頁大小,我們接下來將詳細介紹以上它們對操作系統性能的影響。
頁表項
我們在 為什么 Linux 需要虛擬內存 一文中曾經介紹過 Linux 中的虛擬內存,每個進程能夠看到的都是獨立的虛擬內存空間,虛擬內存空間只是邏輯上的概念,進程仍然需要訪問虛擬內存對應的物理內存,從虛擬內存到物理內存的轉換就需要使用每個進程持有頁表。
為了存儲 64 位操作系統中 128 TiB 虛擬內存的映射數據,Linux 在 2.6.10 中引入了四層的頁表輔助虛擬地址的轉換[^2],在 4.11 中引入了五層的頁表結構[^3],在未來還可能會引入更多層的頁表結構以支持 64 位的虛擬地址。
圖 2 - 四層頁表結構
在如上圖所示的四層頁表結構中,操作系統會使用最低的 12 位作為頁面的偏移量,剩下的 36 位會分四組分別表示當前層級在上一層中的索引,所有的虛擬地址都可以用上述的多層頁表查找到對應的物理地址[^4]。
因為操作系統的虛擬地址空間大小都是一定的,整片虛擬地址空間被均勻分成了 N 個大小相同的內存頁,所以內存頁的大小最終會決定每個進程中頁表項的層級結構和具體數量,虛擬頁的大小越小,單個進程中的頁表項和虛擬頁也就越多。
因為目前的虛擬頁大小為 4096 字節,所以虛擬地址末尾的 12 位可以表示虛擬頁中的地址,如果虛擬頁的大小降到了 512 字節,那么原本的四層頁表結構或者五層頁表結構會變成五層或者六層,這不僅會增加內存訪問的額外開銷,還會增加每個進程中頁表項占用的內存大小。
碎片化
因為內存映射設備會在內存頁的層面工作,所以操作系統認為內存分配的最小單元就是虛擬頁。哪怕用戶程序只是申請了 1 字節的內存,操作系統也會為它申請一個虛擬頁,如下圖所示,如果內存頁的大小為 24KB,那么申請 1 字節的內存會浪費 ~99.9939% 的空間。
圖 3 - 大內存的碎片化
隨著內存頁大小的增加,內存的碎片化情況會越來越嚴重,小的內存頁會減少內存空間中的內存碎片,提高內存的利用率。上個世紀的內存資源還沒有像今天這么豐富,在大多數情況下,內存都不是限制程序運行的資源,多數的在線服務都需要更多的CPU,而不是更多的內存。不過在上個世紀內存其實也是稀缺資源,所以提高稀缺資源的利用率是我們不得不考慮的事情:
圖 4 - 內存的價格
上個世紀八九十年代的內存條只有 512KB 或者 2MB,價格也貴得離譜,但是幾 GB 的內存在今天卻非常常見[^8],所以雖然內存的利用率仍然十分重要,但是在內存的價格大幅降低的今天,碎片化的內存不再是需要解決的關鍵問題了。
除了內存的利用率之外,較大的內存頁也會增加內存拷貝時的額外開銷,因為 Linux 上的寫時拷貝機制,在多個進程共享同一塊內存時,當其中的一個進程修改了共享的虛擬內存會觸發內存頁的拷貝,這時操作系統的內存頁越小,寫時拷貝帶來的額外開銷也就越小。
總結
就像我們在上面提到的,4KB 的內存頁是上個世紀決定的默認設置,從今天的角度來看,這很可能已經是錯誤的選擇了,arm64、ia64 等架構已經可以支持 8KB、16KB 等大小的內存頁,隨著內存的價格變得越來越低、系統的內存變得越來越大,更大的內存可能是操作系統更好的選擇,我們重新回顧一下兩個決定內存頁大小的要素:
過小的頁面大小會帶來較大的頁表項增加尋址時 TLB(Translation lookaside buffer)的查找速度和額外開銷,但是也會減少程序中的內存碎片,提高內存的利用率;
過大的頁面大小會浪費內存空間,造成內存碎片,降低內存的利用率,但是可以較少進程中的頁表項以及 TLB 的尋址時間;
這種類似的場景在我們做系統設計時也比較常見,舉一個不是特別恰當的例子,當我們想要在集群上部署服務時,每個節點上的資源是有限的,單個服務占用的資源可能會影響集群的資源利用率或者系統的額外開銷。如果我們在集群中部署 32 個占用 1 CPU 的服務,那么可以充分利用集群中的資源,但是如此多的實例數會帶來較大的額外開銷;如果我們在集群中部署 4 個占用 8 CPU 的服務,那么這些服務的額外開銷雖然很小,但是可能會在節點中留下很多空隙。
上述就是小編為大家分享的為什么Linux默認頁大小是 4KB了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。