遊戲 Lag 白皮書 › L8 Socket 與協定
TCP HOL 阻塞 Head-of-line blocking
原因 ID sk-hol · 主要負責 遊戲開發團隊(伺服器開發) · 協同 遊戲開發團隊(用戶端開發)
在含圖解與實驗的完整版中開啟卡片 →
TCP 為了維持順序,在重新收到遺失的那一個封包之前,不會把之後到達的封包交給遊戲。
為什麼 一個封包遺失 → 於是 後面的封包都已抵達,卻只能在接收緩衝區等待 → 畫面上 停住之後一口氣全部放行,出現快轉
- 症狀
- 定格, 快轉
- 因素
- 遺失, 停滯
- 誰會遇到
- 只有我
- 何時
- 偶爾隨機發生
- 負責單位
- 主要負責 遊戲開發團隊(伺服器開發) · 協同 遊戲開發團隊(用戶端開發)
- 遊戲開發團隊要做的事
- 伺服器:即時位置改用 UDP,只有真正必要的資料才用可靠傳輸,並拆成多條串流。用戶端:網路處理改成與伺服器相同的方式(UDP、分開通道)。
- 數值參考
- 遺失一個封包至少會停住一個往返時間再多一點,連重傳的封包也遺失時會停住數百 ms~數秒。
- 圖表上
- 中斷後一次湧入 · 每條連線的接收量、重傳次數
- 查看位置
- 用伺服器端的封包擷取(tcpdump、Wireshark)看該玩家連線上的重傳封包及其前後的空白;整個伺服器則看 nstat -az 的 TcpRetransSegs 增加量
- 符合的跡象
- 停住的區間從某一個封包的重傳開始,重傳封包一抵達,積壓的資料就一口氣處理完(接收量先是 0,接著暴增)
- 不符合的跡象
- 用 UDP 通訊的遊戲不適用。沒有重傳卻停住時,要查伺服器 tick(「超出 tick 預算」)
- 確認方式
- 用基礎設施工具確認(不需要遊戲程式碼)
出處
- RFC 9293: Transmission Control Protocol (TCP) IETF
TCP 是可靠且保證順序的位元組串流服務 - RFC 5681: TCP Congestion Control IETF
以 3 個重複 ACK 偵測到遺失時進行快速重傳,否則等待重傳計時器 - RFC 6298: Computing TCP's Retransmission Timer IETF
每次重傳計時器到期就加倍的退避(backoff) - net/ipv4/proc.c (Linux v6.12) Linux kernel
nstat 顯示的計數器名稱:Tcp 群組的 RetransSegs(重傳的區段數)
相關原因
同一層:L8 Socket 與協定
同一症狀(定格)在其他層的原因
查看含圖解與實驗的完整版卡片