遊戲 Lag 白皮書 › L11 磁碟
同步寫入 log Synchronous logging
原因 ID dk-sync-log · 主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(伺服器基礎設施)
在含圖解與實驗的完整版中開啟卡片 →
遊戲執行緒每寫一行 log 都要等磁碟寫完的話,磁碟一忙,遊戲進行也會跟著停住。
為什麼 在遊戲執行緒上直接把戰鬥、交易 log 寫入檔案 → 於是 要求確實寫入(fsync),或 OS 的寫入緩衝區(頁面快取)達到上限時,磁碟一忙,一次寫入就要數十 ms → 畫面上 log 量大的戰鬥中會頓一下
- 症狀
- 卡頓, 定格
- 因素
- 停滯
- 誰會遇到
- 特定地點/頻道, 整個伺服器
- 何時
- 人潮湧入時
- 負責單位
- 主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(伺服器基礎設施)
- 遊戲開發團隊要做的事
- 改用非同步 log(記憶體緩衝區 + 獨立執行緒)、減少 log 量、不在遊戲執行緒上呼叫 fsync。
- 基礎設施團隊要做的事
- 以較低的 I/O 優先順序執行 log 輪替(rotation)與壓縮、把 log 放在與資料不同的磁碟、監控磁碟寫入延遲。
- 圖表上
- 偶爾隨機飆高 · 伺服器 tick 時間、磁碟寫入延遲
- 查看位置
- 把 iostat -x 1 的 w_await、aqu-sz 與 tick 時間疊在一起看,再用 perf trace -p PID --duration 10 找出遊戲伺服器中耗時超過 10ms 的 write、fsync 呼叫及其執行緒
- 符合的跡象
- tick 飆高的時間點,遊戲執行緒的 write、fsync 呼叫耗時數十 ms,同一時刻磁碟寫入延遲也往上衝。常與 log 輪替、壓縮的時間重疊
- 不符合的跡象
- 遊戲執行緒上沒有耗時很久的系統呼叫、tick 卻飆高時,是 GC、鎖、超出 tick 預算等其他原因。只有 log 專用執行緒耗時很久時,不影響遊戲進行
- 確認方式
- 用基礎設施工具確認(不需要遊戲程式碼)
- 深入了解
- OS 通常會先把寫入的資料收進記憶體(頁面快取),之後再寫回磁碟,所以寫一行 log 大多會立刻完成。會停住的情況有三種:用 fsync 要求確實寫入時、積壓的寫入超過上限而使 OS 阻塞(block)寫入呼叫時、輪替或壓縮 log 檔時。因此平常一切正常,只在磁碟忙碌的瞬間飆高。
出處
- fsync(2) — Linux manual page Linux man-pages
fsync 會把變更的資料一路寫到磁碟(包含磁碟快取),並阻塞到裝置回報完成為止 - Documentation for /proc/sys/vm/ Linux kernel
積壓的寫入(dirty)達到 dirty_ratio 時,由執行寫入的處理程序自己負責寫回磁碟 - ionice(1) — Linux manual page util-linux
以 idle I/O 優先順序執行的工作,只有在其他程式沒有使用磁碟時才分得到磁碟時間 - iostat(1) — Linux manual page sysstat
-x:w_await(寫入請求的平均處理時間,包含在佇列中等待的時間)、aqu-sz(平均佇列長度,舊名 avgqu-sz) - perf-trace(1) — Linux manual page perf
用 -p 追蹤執行中處理程序的系統呼叫,用 --duration 只顯示耗時超過指定 ms 的呼叫
相關原因
同一層:L11 磁碟
同一症狀(卡頓)在其他層的原因
查看含圖解與實驗的完整版卡片