RFC-0254:變更寫入頁面內文的出處 | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 變更 Zircon 對寫入寫入頁面的 API 和語意。 |
問題 | |
毛皮變化 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2024-08-02 |
審查日期 (年-月-日) | 2024-07-29 |
問題說明
Zircon 為將記憶體歸因於 VMO 時公開的行為是 以下列兩種方式驗證 Starnix 核心的問題:
首先,Zircon 目前的記憶體歸因行為只能與 在 Zircon 的 VMO 實作中使用廣泛共用的鎖定。這個共用門鎖 是許多 Starnix 程序在執行時會發生問題的原因。
Starnix 利用 VMO 返回每個 MAP_ANONYMOUS
Linux 對應,並複製所有這類
發出 fork()
呼叫時,Linux 程序中的 VMO。透過許多 Linux 程序
結果導致許多 VMO 接續少數共用鎖定我們
設計了可節省記憶體最佳化的原型,Starnix 將單一大型 VMO 用於所有
共用鎖定會產生「global」CANNOT TRANSLATE
星際大戰 VMO 熱烈討論。
第二,Starnix 無法模擬 Linux 記憶體歸因的實際行為
與 Zircon 提供的 API 整合不會區分私人和共用
VMO 中寫入時複製的頁面,因此也不會公開
任何這類分享網頁。Starnix 需要這項資訊來準確計算
在不同 /proc
檔案系統項目中公開的 USS 和 PSS 值。
我們提議變更 Zircon 記憶體歸因 API 的行為,以及 可以解決這些問題,同時維持現有的功能組工具 提供仰賴這些系統的產品資訊我們不會為瞭解決 這種模型會在使用者空間實體 (例如元件和執行器) 之間分配記憶體三 也不該將這些功能轉變為「最後一個字」進行歸因,表示 我們致力解決特定效能瓶頸和功能缺口 快來見識到 Starnix 名人。
摘要
改善 Zircon 的記憶體歸因 API 和行為,以便考量共用情形 寫入後複製的頁面
相關人員
講師:
neelsa@google.com
審查者:
- adanis@google.com
- jamesr@google.com
- etiennej@google.com
- wez@google.com
諮詢:
- maniscalco@google.com
- davemoore@google.com
社交功能:
此 RFC 是在與 Zircon、 《Starnix》和《Memory》團隊利益相關者也查看了設計文件 概述此 RFC 中提議的變更
需求條件
- 核心的記憶體歸因實作不得妨礙最佳化 讓 VMO 階層鎖定更精細地鎖定 Zircon 中的鎖定爭用情形。
- 如果
memory_monitor
等工具能加總系統中所有 VMO 的歸因情形, 且總量必須與系統實際的實體記憶體用量一致。這是 「加總一到一」資源。 - Starnix 必須能夠模擬 Linux 記憶體歸因 APIS 的 以及由 Zircon 提供的 API包括提供 USS、RSS 和 PSS 測量及相關程序檔案系統項目中的其他測量結果。
設計
我們提出的變更會影響 VMO 之間共用 Zircon 屬性頁面的方式 透過寫入時複製的方式複製。這些是 COW 私人網頁和 COW 分享的網頁。
我們不提議變更程序之間共用 Zircon 屬性頁面的方式 讀取及寫入資料這些是程序私密資料 程序共用的頁面
使用者空間負責將程序共用的網頁歸因於一或多個 程序。Zircon 通常不會考慮流程共用 但有一個例外情況請參閱「回溯相容性」的 瞭解詳情
共用類型是各自獨立的,每個網頁都可以是 COW-private、COW 共用、程序私人及程序共用
Zircon 的現有行為
Zircon 現有的歸因行為會提供單一 VM 的評估方式: 來自 VMO 的 COW-private 和 COW 共用頁面的歸因記憶體, 不重複歸因。
- 此屬性可明確將 COW 共用的網頁歸因於現存的最舊 VMO, 參照這些 Pod同一層 VMO 有時會共用 COW 共用頁面,因此 參照頁面最古老的 VMO 不得屬於其他頁面
- 將整個系統的 VMO 總和加總,即為系統記憶體總用量。
- 並不會測量 VMO 的USS,因為其中可能包含「部分」COW 共用網頁。
- 也不會測量 VMO 的 RSS, 因為其中可能不包含「所有」COW 共用的網頁。
- 並不會測量 VMO 的 PSS,因為這項測量結果會縮放各頁面的 貢獻數。
Zircon 的新行為
Zircon 的新歸因行為提供三種每個 VMO 的評估方式:
- USS:從 VMO 的 COW-private 頁面歸因於記憶體。這項測量結果 則只會將頁面歸因於該 VMO它會測量 如果 VMO 遭刪除
- RSS:VMO 的 COW-private 和 COW 共用頁面歸因於記憶體。這個 測量會將 COW 共用的網頁歸給共用這些 VM 的各個 VMO, 會多次計算 COW 共用的網頁。這會測量 VMO 的記憶體總容量 參照。
- PSS:歸因於 VMO 的 COW-private 和 COW 共用頁面所歸因的記憶體。這個 評估方式會在所有 VMO 間平均分配「COW 共用網頁」的歸因情形 共用頁面以指定的 VMO 來說,這可以是小數 因為每個 VMO 各自的共用網頁比例都一樣一個位元組這項服務 會評估 VMO 的「比例」記憶體用量限制將所有 VMO 加總 整個系統是測量系統記憶體總用量。
我們選擇公開所有USS、RSS 和 我們探討了其他解決方案,因此這是 PSS 的唯一選擇 符合所有需求
對使用者空間的影響
此提案將繼續保留「總和」與現有資源
對使用者空間工具至關重要歸因查詢可能會在
新的行為,但繼續加總系統中所有 VMO 的查詢
以便提供準確的記憶體用量。這些變更不會造成程式
例如 memory_monitor
和 ps
,開始超額計算或低估記憶體數量。
事實上,它們會更準確地計算
VMO 和個別工作的計數
新的 API 公開 PSS 的小數位元組值,且使用者空間必須選擇採用
來觀察這些分數的位元組_fractional_scaled
欄位包含
不部分位元組和使用者空間則會稍微低估 PSS 數量。
目前,Starnix 低估了 Linux 對應的 RSS 值,因為 目前的歸因行為只會計算 COW 共用的網頁一次。RSS 應 多次計算共用網頁。Starnix 只有在沒有辦法的情況下模擬這種行為 因此,我們變更 Zircon 歸因 API,以提供正確的 RSS 值。我們可以對另回合的 API 變更執行此操作,不過為了避免 也就是我們選擇批次處理變更
memory_monitor
會將 VMO 視為與參照任何項目的程序共用
任何子項,即使是未直接參照 VMO 的程序也一樣。
也就是將父項 VMO 的歸因記憶體平均分配給這些程序。
試圖將 COW 共用的網頁納入考量,並允許 memory_monitor
:
「加總一次」,但可能會導致一些錯誤結果。舉例來說
部分未參照的父項 VMO 的 COW-private 頁面部分
因此無法參照頁面而且縮放父項時
與部分孩子分享,但不與其他人分享時,可由 COW 分享的網頁。我們的
變更便造成這個行為多餘,而我們也會將其移除。這項工具仍會
當多個程序直接參照 VMO 時
即可調整 VMO 的記憶體詳情請見
「回溯相容性」,掌握更多詳細資訊。
Syscall API 變更
Zircon 的 Attribution API 包含 zx_object_get_info
主題
變更:
ZX_INFO_VMO
- 我們將透過以下方式保留 ABI 和 API 的回溯相容性:
- 將
ZX_INFO_VMO
->ZX_INFO_VMO_V3
重新命名,同時保留其值。 - 正在重新命名「
zx_info_vmo_t
」->zx_info_vmo_v3_t
。
- 將
- 我們將加入新的
ZX_INFO_VMO
和zx_info_vmo_t
,然後改變意義 所有版本的zx_info_vmo_t
中的兩個現有欄位:
- 我們將透過以下方式保留 ABI 和 API 的回溯相容性:
typedef struct zx_info_vmo {
// Existing and unchanged `zx_info_vmo_t` fields omitted for brevity.
// These fields already exist but change meaning.
//
// These fields include both private and shared pages accessible by a VMO.
// This is the RSS for the VMO.
//
// Prior versions of these fields assigned any copy-on-write pages shared by
// multiple VMO clones to only one of the VMOs, making the fields inadequate
// for computing RSS. If 2 VMO clones shared a single page then queries on
// those VMOs would count either `zx_system_get_page_size()` or 0 bytes in
// these fields depending on the VMO queried.
//
// These fields now include all copy-on-write pages accessible by a VMO. In
// the above example queries on both VMO's count `zx_system_get_page_size()`
// bytes in these fields. Queries on related VMO clones will count any shared
// copy-on-write pages multiple times.
//
// In all other respects these fields are the same as before.
uint64_t committed_bytes;
uint64_t populated_bytes;
// These are new fields.
//
// These fields include only private pages accessible by a VMO and not by any
// related clones. This is the USS for the VMO.
//
// These fields are defined iff `committed_bytes` and `populated_bytes` are,
// and they are the same re: the definition of committed vs. populated.
uint64_t committed_private_bytes;
uint64_t populated_private_bytes;
// These are new fields.
//
// These fields include both private and shared copy-on-write page that a VMO
// can access, with each shared page's contribution scaled by how many VMOs
// can access that page. This is the PSS for the VMO.
//
// The PSS values may contain fractional bytes, which are included in the
// "fractional_" fields. These fields are fixed-point counters with 63-bits
// of precision, where 0x800... represents a full byte. Users may accumulate
// these fractional bytes and count a full byte when the sum is 0x800... or
// greater.
//
// These fields are defined iff `committed_bytes` and `populated_bytes` are,
// and they are the same re: the definition of committed vs. populated.
uint64_t committed_scaled_bytes;
uint64_t populated_scaled_bytes;
uint64_t committed_fractional_scaled_bytes;
uint64_t populated_fractional_scaled_bytes;
} zx_info_vmo_t;
ZX_INFO_PROCESS_VMOS
- 我們將透過以下方式保留 ABI 和 API 的回溯相容性:
- 正在將「
ZX_INFO_PROCESS_VMOS
」->「ZX_INFO_PROCESS_VMOS_V3
」重新命名 保留其值
- 正在將「
- 我們將會新增一個
ZX_INFO_PROCESS_VMOS
。- 這個主題重複使用
zx_info_vmo_t
結構體系列,所以變更 這裡就會顯示所有設定
- 這個主題重複使用
- 我們將透過以下方式保留 ABI 和 API 的回溯相容性:
ZX_INFO_PROCESS_MAPS
- 我們將透過以下方式保留 ABI 的回溯相容性:
- 正在將「
ZX_INFO_PROCESS_MAPS
」->「ZX_INFO_PROCESS_MAPS_V2
」重新命名 保留其值 - 正在重新命名「
zx_info_maps_t
」->zx_info_maps_v2_t
。 - 正在重新命名「
zx_info_maps_mapping_t
」->zx_info_maps_mapping_v2_t
。
- 正在將「
- 在下列情況中,我們會中斷 API 相容性:
- 將
committed_pages
和populated_pages
重新命名屬於破壞性變更。 請參閱「回溯相容性」。
- 將
- 我們將新增
ZX_INFO_PROCESS_MAPS
、zx_info_maps_t
和 來使用zx_info_maps_mapping_t
,然後變更「現有」中兩個欄位的意義zx_info_maps_mapping_t
版。但新的 此結構體的版本 (請參閱下文):
- 我們將透過以下方式保留 ABI 的回溯相容性:
typedef struct zx_info_maps {
// No changes, but is required to reference the new `zx_info_maps_mapping_t`.
} zx_info_maps_t;
typedef struct zx_info_maps_mapping {
// Existing and unchanged `zx_info_maps_mapping_t` fields omitted for brevity.
// These fields are present in older versions of `zx_info_maps_mapping_t` but
// not this new version. In the older versions they change meaning.
//
// See `committed_bytes` and `populated_bytes` in the `zx_info_vmo_t` struct.
// These fields change meaning in the same way.
uint64_t committed_pages;
uint64_t populated_pages;
// These are new fields which replace `committed_pages` and `populated_pages`
// in this new version of `zx_info_maps_mapping_t`.
//
// These fields are defined in the same way as the ones in `zx_info_vmo_t`.
uint64_t committed_bytes;
uint64_t populated_bytes;
// These are new fields.
//
// These fields are defined in the same way as the ones in `zx_info_vmo_t`.
uint64_t committed_private_bytes;
uint64_t populated_private_bytes;
uint64_t committed_scaled_bytes;
uint64_t populated_scaled_bytes;
uint64_t committed_fractional_scaled_bytes;
uint64_t populated_fractional_scaled_bytes;
} zx_info_maps_mapping_t;
ZX_INFO_TASK_STATS
- 我們將透過以下方式保留 ABI 和 API 的回溯相容性:
- 在保留時重新命名
ZX_INFO_TASK_STATS
->ZX_INFO_TASK_STATS_V1
。 - 正在重新命名「
zx_info_task_stats_t
」->zx_info_task_stats_v1_t
。
- 在保留時重新命名
- 我們將新增
ZX_INFO_TASK_STATS
和zx_info_task_stats_t
,並且 變更「所有」版本中三個現有欄位的意義zx_info_task_stats_t
結構體:
- 我們將透過以下方式保留 ABI 和 API 的回溯相容性:
typedef struct zx_info_task_stats {
// These fields already exist but change meaning.
//
// These fields include either private or shared pages accessible by mappings
// in a task.
// `mem_private_bytes` is the USS for the task.
// `mem_private_bytes + mem_shared_bytes` is the RSS for the task.
// `mem_private_bytes + mem_scaled_shared_bytes` is the PSS for the task.
//
// Prior versions of these fields only considered pages to be shared when they
// were mapped into multiple address spaces. They could incorrectly attribute
// shared copy-on-write pages as "private".
//
// They now consider pages to be shared if they are shared via either multiple
// address space mappings or copy-on-write.
//
// `mem_private_bytes` contains only pages which are truly private - only one
// VMO can access the pages and that VMO is mapped into one address space.
//
// `mem_shared_bytes` and `mem_scaled_shared_bytes` contain all shared pages
// regardless of how they are shared.
//
// `mem_scaled_shared_bytes` scales the shared pages it encounters in two
// steps: first each page is scaled by how many VMOs share that page via
// copy-on-write, then each page is scaled by how many address spaces map the
// VMO in the mapping currently being considered.
//
// For example, consider a single page shared between 2 VMOs P and C.
//
// If P is mapped into task p1 and C is mapped into tasks p2 and p3:
// `mem_private_bytes` will be 0 for all 3 tasks.
// `mem_shared_bytes` will be `zx_system_get_page_size()` for all 3 tasks.
// `mem_scaled_shared_bytes` will be `zx_system_get_page_size() / 2` for p1
// and `zx_system_get_page_size() / 4` for both p2 and p3.
//
// If P is mapped into task p1 and C is mapped into tasks p1 and p2:
// `mem_private_bytes` will be 0 for both tasks.
// `mem_shared_bytes` will be `2 * zx_system_get_page_size()` for p1 and
// `zx_system_get_page_size()` for p2.
// `mem_scaled_shared_bytes` will be `3 * zx_system_get_page_size() / 4` for
// p1 and `zx_system_get_page_size() / 4` for p2.
uint64_t mem_private_bytes;
uint64_t mem_shared_bytes;
uint64_t mem_scaled_shared_bytes;
// This is a new field.
//
// This field is defined in the same way as the "_fractional" fields in
// `zx_info_vmo_t`.
uint64_t mem_fractional_scaled_shared_bytes;
} zx_info_task_stats_t;
實作
我們會實作結構核心 API 變更 (例如新增及重新命名
) 做為單一初始 CL,以降低客戶流失率。我們會將這個數值
將新欄位設為 0,但 _fractional_scaled
欄位的設定除外
設為 UINT64_MAX
的禮盒值。
接下來,我們會變更有關歸因父項的 memory_monitor
行為
處理及使用 VMO 記憶體,以便處理及使用 PSS _scaled_bytes
欄位
RSS _bytes
欄位。_fractional_scaled
中的標記值
欄位會暫時限制這兩種無法回溯相容的行為。這個
其他新欄位中的值 0 表示不會發生使用者空間行為
不會有變更
接著,我們會公開核心的新歸因行為。這項異動
將會改變現有欄位 (例如 committed_bytes
) 和新的
欄位可採用非零的值。_fractional_scaled
欄位不得包含
這樣就會繼續採用 Sentinel 值
以便利用新的行為和新欄位善加利用
最後,我們會將檢查工具中 _fractional_scaled
欄位的檢查移除:
memory_monitor
。
我們變更的舊版 API 視為已淘汰。我們可以移除 之後,若我們確信二進位檔不再符合這些條件,就會發生上述情形。
成效
導入新的歸因模式可提高歸因成效 舉個簡單的例子,您可以定義情境 並指示 AI 如何回應服務中心查詢可減少處理 VMO 複製作業的次數,避免產生昂貴的檢查費用, 來區分多部 VMO 之間共享的 COW 頁面。
之後,導入精細的階層鎖定將能提升
頁面錯誤和多個 VMO 系統呼叫,包括 zx_vmo_read
、zx_vmo_write
、
zx_vmo_op_range
和zx_vmo_transfer_data
。這些行動延續於
所有相關 VMO 共用的階層鎖定
對相關 VMO 副本執行的作業反之,如果 VMO 的虛擬機器
以便執行複製作業許多 Starnix 和啟動檔案系統 VMO 都屬於這個類別。
Zircon 會在建立及刪除子項 VMO 時執行更多工作,建立中
SNAPSHOT
和 SNAPSHOT_MODIFIED
子項會改為 O(#parent_pages)
(共 O(1)
個)。如果刪除任何類型的子項,在任何情況下都會變成 O(#parent_pages)
在某些情況下,這些可能有助於 O(#child_pages)
。Zircon 目前
將這項工作延遲到更頻繁的作業,例如頁面錯誤。移動到
不常的 zx_vmo_create_child()
和 zx_vmo_destroy()
作業將會
加快其他常用作業的商業速度我們預期
而這也成為使用者可見的效能迴歸
我們將使用現有的 Microbenchmark 和 Macrobenchmark 來驗證是否 成效差異
回溯相容性
ABI 與 API 相容性
我們會為所有核心 API 變更建立其他版本化主題,並 但會保留所有現有主題的支援這樣可保留 ABI 相容性 以及 API 相容性
正在重新命名 zx_info_maps_mapping_t
中的 committed_pages
和 populated_pages
就是破壞 API這些欄位僅用於 Fuchsia-internal
由於 CL 能夠為這些欄位重新命名
變更所有通話網站的名稱。
其他變更則不需要更新現有的通話網站,除非對方願意 並利用新加入的欄位
行為相容性
Starnix、ps
和一些程式庫 (獨立 VMO 或
每項工作的 RSS 值新的歸因行為會用來計算
更準確。因為這類報表會重複計算 COW 共用的網頁。這個
會以回溯不相容的方式變更 RSS 值
所以我們不希望造成任何負面影響。
memory_monitor
為父項 VMO 歸因記憶體的方法正確無誤
新歸因行為能修正的問題我們必須變更這項工具的
無法回溯相容實作修正。為了避免
流失,我們會將新的 _fractional_scaled
欄位設為
UINT64_MAX
,直到我們導入新的歸因行為為止。我們會出門
memory_monitor
以此值進行實作。一律不產生歸因
和一般的標準化值,所以看起來很不錯。
我們會保留「共用」的意思"程序共用"在「ZX_INFO_TASK_STATS
」中
但運作方式與其他 Attribution API 不同這樣一來,
仰賴 ZX_INFO_TASK_STATS
行為的現有程式才能繼續
以免產生侵入式變更未來的工作可能會取代上述做法
有不同查詢,可能是 memory_monitor
,時間為 ZX_INFO_TASK_STATS
我們就可以淘汰並移除 ZX_INFO_TASK_STATS
。
測試
核心測試套件已有許多測試來驗證記憶體歸因。
我們會新增幾項測試,驗證新歸因的極端情況 API 和行為
說明文件
我們將更新 zx_object_get_info
的 syscall 說明文件,以反映這些
並輸入變更內容
我們會在 docs/concepts/memory
下新增頁面,用來描述 Zircon 的
記憶體歸因 API 並提供範例
缺點、替代方案和未知
在開發這項技術的過程中 提案。這些大多數發布商容易導入,但成效不彰。 維護特徵
模擬目前的歸因行為
如果採用這個選項,我們會將核心變更為模擬現有的歸因 新實作上的行為
它沒有回溯相容性方面的疑慮,也不需要任何 API 變更。
但會禁止使用精細的階層鎖定功能 現有的共用階層鎖定功能就能運作這項模擬會導致 進行更精細的鎖定策略,分析查詢死結。會 也會導致歸因查詢的成效不佳這些廣告活動的成效 關注的議題最後,這個介面並未提供 Starnix 需要的資訊 計算 USS、RSS 或 PSS 等測量結果。
隻公開 USS 和 RSS
如果採用這個選項,我們會變更核心,改為歸因於寫入時共用複製功能 分享資訊,並公開提交資訊,將這項資訊提供給私人大眾和分享
這種架構與精細的階層鎖定相容。
不過,它無法提供足夠的資訊來保存使用者 「加總一到一」屬性。如要計算 PSS 測量結果,則建議使用 Starnix。核心 這個選項會為 COW 共用網頁多次屬性。每一份 COW 共用的資料 網頁分享次數可能會因寫入模式而異 的使用者空間中,需要單頁資訊才能刪除重複的 COW 共用網頁,或 平均分配到本機副本之間
顯示每個 VMO 樹狀結構的詳細資料
如果採用這個選項,我們會變更核心,改為歸因於寫入時共用複製功能 並公開每個樹狀結構和 VMO 的資訊:
- 將 VMO 連結至其樹狀結構的樹狀結構 ID
- 每個 VMO 的穩定 ID,適用於建立中斷事件,例如時間戳記
- 每個 VMO 的私人頁面數
- 每個樹狀結構的共用網頁總數
- 每個 VMO 可見的每個樹狀結構共用頁面數量
提供使用者空間,滿足「加總一個」的需求 資源。
然而,這卻阻擋了我們想進行的鎖定爭用最佳化 需要現有的共用階層鎖定功能才能運作。無論 計算「每個樹狀結構的共用網頁總數」而且沒有這種共同的鎖這個 選項也會向使用者空間公開核心實作詳細資料 VM 程式碼日後的維護也更加困難且不提供 資訊 Starnix 需要計算 PSS 測量結果。
既有藝術品和參考資料
其他作業系統會提供 RSS、USS 和 PSS 測量結果,用於 有時可能會使用不同的名稱Windows、MacOS 和 Linux 所有曲目 RSS 和 USS。Linux 型作業系統追蹤 PSS。
Linux 會透過程序檔案系統公開這些測量結果。歸因工具 例如 ps 和頂端