RFC-0084:在 zx_info_task_runtime_t 中加入更多指標 | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 將其他指標新增至 zx_info_task_runtime_t,以便對媒體效能問題進行偵錯。 |
問題 | |
毛皮變化 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2021-03-09 |
審查日期 (年-月-日) | 2021-04-06 |
摘要
ZX_INFO_TASK_RUNTIME
主題可讓您擷取
工作在 CPU 或佇列中執行所花費的時間。診斷時
排程瓶頸,建議新增其他精細執行階段
尤其是等待頁面錯誤
等待核心互斥鎖所花費的時間。
提振精神
即時工作設有期限。有時工作會因為工作而錯過期限 在核心中執行非預期長的時間如要對這些情況進行偵錯 會很有幫助。舉例來說 但花費 10 毫秒,但等待 11 毫秒,頁面發生錯誤時,我們就認定 網頁錯誤速度太慢,因此超過期限。
具體來說,我們希望改善媒體子系統產生的診斷資料,例如
audio_core
。在 audio_core
中,每個混合器工作必須在 10 毫秒內完成。如果
工作耗時超過 10 毫秒,使用者將會聽到音訊不流暢的情形。最近我們
因網頁錯誤速度緩慢 (其中 audio_core
可執行) 而錯過期限
重新分頁) 和呼叫核心的堆積互斥鎖
這些問題無法用快照診斷,因此我們必須
是一項繁瑣的程序,但有時難以執行
在本機重現問題 (因為錯誤可能只會在有特定要求時觸發,
特定環境中的 App Engine 應用程式)。這些是高度優先的問題,而且
嚴重對媒體成效造成負面影響。
我們的目標是從核心匯出足夠的診斷資訊,
可以從快照診斷問題,不必深入瞭解
執行追蹤記錄本文件建議在
zx_info_task_runtime_t
以更全面地回答以下問題:「為什麼這是什麼原因?」
「無法執行任務嗎?」
Zircon 執行緒期限的背景
Zircon 期限設定檔包含三個部分:經期、容量和期限。 為執行緒指派期限設定檔時,Zircon 會確保每個執行緒 period 則會在 每個期間的開頭。請參考以下示例:
- 期間 = 10 毫秒
- 容量 = 2 毫秒
- 期限 = 5 毫秒
每 10 毫秒,執行緒就會在接下來的 5 毫秒內分配 2 毫秒的 CPU。另有 不符合期限的兩種做法:
這項工作已排定遲交。例如,如果下個經期是從時間開始 T,但工作必須安排在 T+4 毫秒後完成,因此這項作業不可能 使工作達到期限 (應該排定在 T+3 毫秒)。核心可以偵測這類錯過的期限 但在實務上 除非排程器發生錯誤或超額訂閱,否則一律不會發生這種狀況。
工作需要超過 2 毫秒才能完成。核心無法得知何時 原因是無法理解任務邊界舉例來說, 工作安排在 T+1 毫秒執行,執行總時間為 1 毫秒,接著封鎖 9 毫秒。 核心無法得知工作是否已超過其期限 (因為 或者工作要求 2 毫秒,但只需要 1 毫秒, 完成 (然後睡眠 9 毫秒,等待下一個經期)。
我們的目標是幫助診斷第二類錯過的期限。目前,
工作執行時間過長,可以查詢 ZX_INFO_TASK_RUNTIME
來瞭解
使用者空間在 CPU 上執行的時間。如果 cpu_time
大於
任務的預期執行階段,該工作知道只是執行了過長而已。不過
如果 cpu_time
是總工作時間的一小部分,則工作
在核心中大部分的時間,可能遭阻斷而無法執行。目標
的用意是協助瞭解時間花費的時間
設計空間
我們的目標是回答「為何這項工作無法執行?」這個問題。我們必須 做一些決定:
我們的回答是否完整?具體而言, 為何工作遭封鎖,或僅有幾個重要原因?
我們應該在多精細的程度上回答這個問題。舉例來說 只會回報使用者層級可理解的簡單事件,例如 「在 zx_channel_read 遭到封鎖」或者包含層級較低的事件 是否與 Zircon 目前的實作相關?
如果我們回報 N 的統計資料,就必須要求 N 統計 是否彼此重疊,或者是否該開放它們互相重疊?
最簡單也最直接的做法是列舉幾個我們關注的事件 並產生這些事件的統計資料媒體子系統 頁面錯誤和核心鎖定爭用時,我們可能會產生 「網頁錯誤花費時間」的統計資料以及「在核心上遭到封鎖的時間」 鎖定」
除了這兩種廣告以外,您可能還無法掌握其他潛在的問題 統計資料。因此,完整的解決方案才有吸引力。列舉一個概念 讓執行緒可進入核心的所有可能方式包括 N 硬體 中斷 (計時器和裝置中斷) 和 K 軟體中斷 (系統) 呼叫與錯誤)。然後產生 N+K 統計資料, 幹擾。計時器會在執行緒進入核心時啟動,並在出現以下情況時停止: 控制項會傳回使用者空間執行緒。不過,使用者層級 「在 syscall X 花費的時間」,讓核心計算出此資訊 是多餘的。
另一個概念是產生統計資料「使用時 核心模式」和「在 X 上遭到封鎖的時間」,其中 X 是一組核心 例如「核心鎖定」或「管道」這個想法有膨脹的風險 而核心數量會隨著時間逐漸變動
我們要退一步,我們真正想要的是從外部裝置擷取追蹤記錄。
理想情況下,我們會持續將追蹤記錄錄製到圓形緩衝區中
緩衝處理完成後
TRACE_ALERT
。
設計
我們當然有理想的解決方案 設計與建構我們急需診斷效能降低的情況 。因此,我提議增加兩個目標指標,以解決我們的 立即問題:等待頁面錯誤而花費的時間 也就是等待核心鎖定所花費的時間。
關於上述設計空間相關問題:
我們不會追求完整性。
精細程度是任意選項 (我們會記錄任何我們認為所需的內容)
統計資料可能會以任意方式重疊
核心變更
// This struct contains a partial breakdown of time spent by this task since
// creation. The breakdown is not complete and individual fields may overlap:
// there is no expectation that these fields should sum to an equivalent
// "wall time".
typedef struct zx_info_task_runtime {
// Existing fields
zx_duration_t cpu_time;
zx_duration_t queue_time;
// New fields below here
// The total amount of time this task and its children spent handling page faults.
zx_duration_t page_fault_time;
// The total amount of time this task and its children spent waiting on contended
// kernel locks.
zx_duration_t lock_contention_time;
} zx_info_task_runtime_t;
系統會依執行緒計算這兩個欄位,然後在程序之間加總
以及 cpu_time
和 queue_time
目前完成的工作。請注意,
媒體子系統不需要對個別程序和每項工作進行匯總,但
加入到這裡,以便與
zx_info_task_runtime_t
。
頁面錯誤和多個核心鎖定分成多種類型,
page_fault_time
代表處理各種網頁所花費的總時間
也會發生故障藉由涵蓋所有網頁錯誤,我們不必說明
這可能不容易,因為核心可能會新增
導入作業會隨時間變化,並且移除特定類型的網頁錯誤,
支援新架構
lock_contention_time
可涵蓋所有意外鎖定。但所指稱的「困難」
保留刻意指定,因此核心可能會改進其實作方式
以便平衡評估爭用成本與
報告所需時間如需進一步討論,請參閱導入作業 (請見下文)。
使用者空間如何診斷未及時指定的期限
由於這些新欄位,使用者空間可以使用類似下方的程式碼來診斷 錯過的期限:
for (;;) {
zx_object_get_info(current_thread, ZX_TASK_RUNTIME_INFO, &start_info, ...)
deadline_task()
if (current_time() > deadline) {
zx_object_get_info(current_thread, ZX_TASK_RUNTIME_INFO, &end_info, ...)
// ...
// report stats from (end_info - start_info)
// ...
}
}
實作
page_fault_time
會計算所有頁面錯誤處理常式花費的總時間。
在目前的實作中,這包括 vmm_page_fault_handler
和
vmm_accessed_fault_handler
。
lock_contention_time
會計算
Mutex::AcquireContendedMutex
和BrwLock::Block
。這個方法
存取目前的Thread
和current_ticks()
。實作方式
不會遮住旋轉鎖頭雖然旋轉鎖可能很常發生,但我們會忽略旋轉
因為如要測量旋轉鎖的爭用情形,可能會暫時鎖定
。
為了盡可能減少額外負荷,我們會將這些時間長度記錄為滴答聲,
則會在 zx_object_get_info
系統呼叫期間轉譯為 zx_duration_t
。
其他實作細節會沿用
《cpu_time
》和《queue_time
》。原型導入網址為
fxrev.dev/469818。
成效
我們將執行 Zircon Mutex 基準測試,確認沒有任何迴歸問題。我們會 這些基準測試是在原始硬體 (x86 和 ARM) 上執行。此外,如要驗證 虛擬化環境內不會有迴歸 為 QEMU (x86 和 ARM) 基準。
回溯相容性
zx_info_task_runtime_t
結構會進行版本管理,與先前版本相似
完成其他 zx_info_*
結構體的作業 (例如,請參閱 fxrev.dev/406754)。
安全性考量
「ZX_INFO_TASK_RUNTIME
」是一個側邊管道,可能會洩露
已檢查工作。舉例來說,page_fault_time
可用於測量工作的
記憶體存取模式為了緩解這種外洩事件,
「ZX_INFO_TASK_RUNTIME
」主題已有 ZX_RIGHT_INSPECT
。具有
即可假設使用者擁有工作私人資料的存取權。
ZX_INFO_TASK_RUNTIME
可能也會洩露其他工作的間接資訊。適用對象
舉例來說,如果工作知道自己的 page_fault_time
,系統或許能推斷出
「其他」工作的記憶體存取模式。同樣地,如果工作知道
進而推斷出如何
也會使用共用核心資源未來我們可能會在
使用低解析度計時器zx_info_task_runtime_t
。這不一定
可以防止時間攻擊,但可以限制其有效性。
另一項防護是限制特殊開發人員可以存取「zx_info_task_runtime_t
」
建構應用程式不過,這樣會大幅限制這項功能的實用性:
所以在開發環境中,我們通常無法重現效能錯誤。
我們需要可以在正式版本中啟用的解決方案。
為避免這個側邊管道完全採用,我們需要區隔指標報表
和指標檢查拆分為不同的功能。舉例來說
將追蹤記錄持續錄製到環形緩衝區中,然後將該緩衝區上傳至
或是他造訪 YouTube 數據分析的
TRACE_ALERT
、
那麼無需提供觸發 TRACE_ALERT
的任務
就能排除側邊管道。稍早提過
這樣的解決方案需要很長的時間來設計及建構
需要立即解決問題
隱私權注意事項
無。
說明文件
Zircon syscall 說明文件需要更新,加入新的
zx_info_task_runtime_t
欄位。
既有藝術品和參考資料
在 Linux 中,最為相關的前項是 getrusage
,這是回報使用者的資訊
以及系統 CPU 作業時間和頁面錯誤數、I/O 作業和環境切換。
Windows 的 GetThreadTimes
會回報使用者和系統 CPU 作業時間。硬體
效能計數器 (例如 x86 上的 RDPMC
) 會提供類似的資訊,以及
擁有
類似的安全疑慮。
測試
我們會透過 audio_core
記錄新的執行階段資訊,以手動方式進行測試
(我們也已經完成原型導入作業:請參閱
fxrev.dev/469819)。
我們會更新 cpu_time
和 queue_time
的現有測試,以測試舊的
zx_info_task_runtime_t
的新版本,將會命名
zx_info_task_runtime_v1_t
。此外,Zircon 的
abi_type_validator.h
,以便驗證新舊 ABI。如此能確保 ABI
保有回溯相容性
要為這項功能新增整合測試並不容易,因為 沒有 API 可強制核心進行鎖定爭用或觸發頁面錯誤 (除程序終止區隔錯誤以外)。