한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Sách trắng lag game › L1 Tiến trình game phía client

Thu gom rác (GC) phía client Client GC (Unity C#, Unreal, Lua)

ID nguyên nhân cg-gc · Phụ trách chính Phát triển client (Đội phát triển game)

Mở thẻ gốc có hình minh họa và thí nghiệm →

Trong lúc thu hồi bộ nhớ đã dùng xong (rác), cả game dừng lại. Đặc trưng là giật khựng theo khoảng cách đều đặn.

Vì sao Mỗi khung hình đều tạo rồi bỏ các chuỗi, mảng, list tạm → Dẫn đến Rác dồn lại thì GC dừng main thread để thu hồi → Trên màn hình Cứ vài giây đến vài chục giây lại giật khựng đều đặn

Triệu chứng
Giật khựng, Đứng hình
Yếu tố
Ngưng trệ
Ai gặp phải
Chỉ mình tôi
Khi nào
Theo chu kỳ đều, Khi đông người
Phụ trách
Phụ trách chính Phát triển client (Đội phát triển game)
Việc cần làm (Đội phát triển game)
Giảm cấp phát (tránh nối chuỗi, LINQ, capture biến trong lambda), dùng object pool, bật incremental GC (mặc định từ Unity 2020), chủ động chạy GC vào lúc dừng cũng không sao, như màn hình loading.
Con số tham khảo
Thường mỗi lần mất vài ms đến 100 ms; trên điện thoại cấu hình thấp hoặc game dùng nhiều bộ nhớ thì lâu hơn (trong thí nghiệm khoảng 150–170 ms). GC của Unity quét toàn bộ heap mỗi lần chạy, nên game đang dùng càng nhiều bộ nhớ thì mỗi lần dừng càng lâu.
Trên đồ thị
Vọt lên theo chu kỳ · Frame time, thời điểm GC chạy
Chỗ cần xem
Marker GC.Collect, GC.Alloc trong Unity Profiler trên bản build development. Với Unreal: stat GC và stat Hitches (ghi log các khung hình vượt ngưỡng đặt bằng t.HitchFrameTimeThreshold)
Đúng nếu
khung hình nào vọt lên cũng có đoạn GC.Collect dài xấp xỉ mức vọt, cách nhau đều đặn vài giây đến vài chục giây. Ở nơi đông người, GC.Alloc mỗi khung hình tăng lên
Loại trừ nếu
khung hình vọt lên không có đoạn GC → xem “Tải đồng bộ trên main thread và biên dịch shader” hoặc “Tải render khi đông người”
Cách kiểm tra
Cần log và chỉ số của server, client game
Tìm hiểu thêm
Hiện tượng này phổ biến ở client viết bằng C# như Unity. Thủ phạm chính là code tạo mới chuỗi log chiến đấu, số sát thương, chữ trên UI ở mỗi khung hình. Nếu chỉ giật ở nơi đông người, nghĩa là có đoạn code sinh rác tăng theo số người. Incremental GC chia việc thu gom thành từng phần nhỏ ở mỗi khung hình (mặc định của Unity là 3 ms), nhưng nếu rác sinh ra nhanh hơn tốc độ thu gom thì cuối cùng game vẫn dừng một lượt. Unreal Engine cũng có GC riêng để dọn các game object không còn dùng. Tùy phiên bản engine và cấu hình, với thiết lập mặc định GC này chạy khoảng 1 phút một lần và có thể gây khựng cách nhau 1 phút. Client viết luật game bằng script như Lua còn có thêm GC riêng của script đó.

Nguồn

  1. Garbage collection modes Unity
    Incremental GC là mặc định và thu gom rải ra nhiều khung hình; nếu tắt, main thread dừng trong lúc quét toàn bộ heap, có thể tới hàng trăm ms
  2. Scripting.GarbageCollector.CollectIncremental Unity
    Thời gian mỗi lượt của incremental GC (time slice) có mục tiêu mặc định là 3 ms (incrementalTimeSliceNanoseconds)
  3. Garbage Collection Settings in the Unreal Engine Project Settings Epic Games
    Thiết lập cho GC của Unreal chạy theo khoảng cách cố định (Time Between Purging Pending Kill Objects, tính bằng giây). Tài liệu này không ghi con số mặc định
  4. Profiler markers reference Unity
    GC.Collect: khoảng thời gian code chương trình dừng trong lúc thu gom rác (dưới 1 ms đến hàng trăm ms); GC.Alloc: cấp phát trên managed heap
  5. Stat Commands in Unreal Engine Epic Games
    stat GC (thống kê thu gom rác), stat Hitches (ghi log các khung hình vượt t.HitchFrameTimeThreshold)

Nguyên nhân nên xem cùng

Cùng tầng: L1 Tiến trình game phía client

Nguyên nhân ở tầng khác gây cùng triệu chứng (Giật khựng)

Xem thẻ gốc có hình minh họa và thí nghiệm