RFC-0016:啟動頁面大小

RFC-0016:啟動時間頁面大小
狀態已接受
區域
  • 核心
說明

將 PAGE_SIZE 常數換成 vdsocall。

變更
作者
審查人員
提交日期 (年/月)2020-12-02
審查日期 (年/月)2021-01-12

摘要

基於富士薩的系統,應能利用較大的頁面大小,以達到最佳效能。為了達到這項可行的網頁大小,頁面大小必須是執行時間,而不是編譯時間。此常數應由核心在啟動期間以某種方式決定,然後透過 VDSO 提供使用者的執行時間查詢。

提振精神

為了獲得最佳效能,系統應要能根據已知的靜態資訊或在啟動時查詢的頁面大小選取頁面大小。此外,靜態決策應隨需求或需求改變而變更,最好以非 ABI 破壞的方式進行。

頁面大小不同,效能的取捨。較大的頁面可以提升有效的 TLB 涵蓋範圍,並按比例提高對頁面精細程度的任何演算法或運算效能 (例如頁面配置、錯誤和掃描) 的效能,進而減少 CPU 負擔。如果大型頁面能降低頁面表格的記憶體使用率,也會造成超額配置而浪費記憶體,因此這種較小的頁面可以提供更最佳的記憶體用量。

效能與記憶體用量的取捨可能取決於硬體和系統工作負載。在系統啟動時通知使用者頁面大小,可讓您在核心編譯時間靜態變更頁面大小,或在核心啟動時動態變更頁面大小,而不會破壞與使用者層級元件的二進位檔相容性。

設計

方法是在 VDSO 中新增一個額外常數,並透過 VDSO 呼叫 (zx_system_get_page_size) 進行擷取。接著,您可以將所有現有編譯時間常數的用法改為使用 VDSO 呼叫,直到編譯時間常數可以移除為止。

也請務必為每個平台宣告頁面大小下限和上限。這是為了讓使用者知道連結頁面大小上限,以確保元件可攜性。

實作

實作有三個階段。雖然使用的是 C/C++ 名稱,但仍需為所有 Fuchsia 支援語言執行對應作業。

  1. 新增 zx_system_get_page_size VDSO 呼叫和相關聯的 VDSO 常數,以及 PAGE_MIN_SIZEPAGE_MAX_SIZE 定義。
  2. 遷移 PAGE_SIZE (或對應語言) 的使用情形,以便使用 VDSO 通話
  3. 移除未使用的 PAGE_SIZE (或語言對等) 定義。

第一個和第三個階段平易近人,而且會是小型 CL。

遷移階段應保持精簡,但應盡可能按照元件設定每個 CL 來計算。

雖然並非完全屬於這個 RFC,但如要實際變更指定產品的頁面大小,還需要完成下列設定:

  1. 針對大型頁面提供低階核心實作支援。
  2. 使用者元件 (例如 BlobFS) 必須修改,才能支援非 4KiB 頁面。
  3. ELF 區段的對齊必須增加,以免頁面要求重疊的安全性權限。

效能

雖然這可以將編譯時間常數遷移至執行階段查詢,但由於系統對任何熱路徑的計算結果不知道網頁大小,因此預期會造成任何可評估的效能影響。不過,在遷移至 VDSO 呼叫時,如果發現並非處於初始化或測試程式碼的使用情形,應該就會記下其效能,評估後的效果。

安全性考量

隱私權注意事項

測試

現有測試應足以找出遷移期間可能出現的任意錯誤。遷移元件中的任何程式碼時,應檢查測試的程式碼涵蓋率。

說明文件

zx_system_get_page_size VDSO 通話需要記錄。說明文件內容應會

  • 這是所有配置的最小頁面大小和基本單位。
  • Vdsocall 永遠不會失敗。
  • 頁面大小保證是 2 的次方。
  • 讀取一次的頁面大小是固定的,且使用者可快取。

VMO 及其他記憶體相關系統呼叫和物件的現有說明文件,若為抽象,一律參照「系統頁面大小」。

平台說明文件應含有頁面大小上下限和上限,且應反映 PAGE_MIN_SIZEPAGE_MAX_SIZE 常數。這些值

  • ARM aarch64:最小 4KiB,最大 64KiB。
  • x86-64:最小 4KiB,最大 2 MiB。

缺點、替代方案和未知

系統頁面大小主要與使用者正確執行 VMO 作業,或是透過其他 Fuchsia 服務實作通訊協定。因此,非典型的原生程式碼需要知道頁面大小,或是需要依賴該程式碼時,頁面大小並不容易。不過,如果發生這種情況,可能需要修改來源以便進行通訊埠。

從編譯時間常數執行遷移作業,雖然概念上沒有複雜性,但這麼做會導致程式碼流失,而且在過程中產生錯誤的機會也相當大。

移除編譯時間常數的參照不代表程式碼實際上可以容許不同的頁面大小。演算法相當有機會將目前的 4KiB 頁面大小做出假設,或單純自行定義頁面大小常數。如果編譯時間常數有所變更,也會發生這些錯誤,因此應視為不相關的錯誤。

主要替代方案是繼續使用編譯時間常數,但針對特定產品修正這項錯誤,或針對特定產品修正部分組合。修正特定產品可能適用於部分受到嚴格控管的產品,但較不適合長期執行產品,而該產品較不適合在不同硬體疊代作業中長期確保二進位檔相容性。如要建構多個版本的二進位檔,而且必須使用不同頁面大小,就能達到想要的靈活性,但是對開發人員的時間和儲存空間來說,成本很高。一般來說,採用編譯時間常數會帶來多項缺點,而且唯一可察覺的缺點是避免一次遷移。

相較於啟動時間常數,頁面大小或許是實際變數,並可能會隨著時間變動,或因不同元件而異。雖然這可提供極致的彈性,但由於 VMO 等物件可將語意連結至頁面大小,但嘗試在不同元件之間任意共用頁面大小,試圖讓使用者同時嘗試不同的頁面大小,會對查詢造成不合理的負擔,並避免變更頁面大小的競爭狀況。當頁面大小不同時,如果頁面大小不同,將有利於特定的子系統,並明確採用某些獨立的子系統來明確選擇啟用 VMO,否則就應該開發出頁面大小最佳化。

如果應用程式知道網頁大小以位元為單位,就能執行位移算術,這個做法也很實用。您也可以新增 zx_system_get_page_shift,或是不新增 zx_system_get_page_size。由於使用位移屬於微最佳化類型,因此只有在應用程式快取 Vdsocall 的結果時,可能才能受益。因此,當使用者將頁面大小轉換成位移和快取時,等於等同於變更頁面大小。因此,以 vdsocall 的形式提供這兩種變數並不會帶來實際好處。

先前的圖片和參考資料

透過 sysconf(_SC_PAGE_SIZE) 的 Unix 衍生內容報表頁面大小。

PAGE_SIZE 編譯時間常數會以常數程式碼的形式,以及部分分佈情形做為 <sys/user.h> 的一部分提供,但該常數並非標準或可攜性。

Windows 會透過 GetSystemInfo() 系統呼叫回報頁面大小。

macOS 會透過 sysctl() 呼叫或 vm_page_size 變數來回報頁面大小。