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

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

Tranh chấp lock Lock contention

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

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

Khi nhiều thread cùng chờ một lock để ghi cùng một dữ liệu, dù có thêm thread thì mỗi lúc cũng chỉ một thread chạy.

Vì sao Nhiều thread cùng lúc dùng dữ liệu chung, như sàn đấu giá hoặc kho bang hội → Dẫn đến Các thread còn lại phải chờ đến khi thread đang giữ lock làm xong → Trên màn hình Chỉ một số tính năng bị chậm, nặng thì cả tick bị trễ

Triệu chứng
Trễ thao tác, Đứng hình
Yếu tố
Ngưng trệ
Ai gặp phải
Chỉ một tính năng, Cả server
Khi nào
Khi đông người
Phụ trách
Phụ trách chính Phát triển server (Đội phát triển game)
Việc cần làm (Đội phát triển game)
Chia lock nhỏ ra, giảm việc làm bên trong lock, chuyển sang kiến trúc dựa trên message (mỗi dữ liệu có một thread phụ trách, các thread khác chỉ gửi yêu cầu bằng message).
Con số tham khảo
Nếu phần việc nằm trong lock chiếm 20% công việc, dù tăng thêm bao nhiêu thread, thông lượng tối đa cũng chỉ gấp 5 lần so với khi chạy 1 thread; nếu là 40% thì dừng ở mức 2,5 lần.
Trên đồ thị
Tăng theo số người và tải · Thời gian xử lý yêu cầu, CPU và context switch theo từng thread
Chỗ cần xem
Context switch tự nguyện theo từng thread (cswch/s, số lần dừng để chờ tài nguyên) qua pidstat -w -t 1; thread rời CPU rồi chờ ở đâu (thời gian chờ theo từng call stack) qua bcc offcputime -p. Với .NET, xem số lần tranh chấp lock trong dotnet-counters (dotnet.monitor.lock_contentions từ .NET 9, Monitor Lock Contention Count ở bản 8 trở xuống)
Đúng nếu
tải tăng mà mức sử dụng CPU vẫn thấp nhưng thời gian xử lý tăng, phần lớn thời gian chờ dồn vào các call stack đang cố lấy lock, và số lần tranh chấp lock tăng theo
Loại trừ nếu
CPU đầy → vấn đề khối lượng tính toán (vượt tick budget, quá tải khu vực chạy trên một thread). Chỗ chờ là lời gọi DB hoặc file → gọi đồng bộ trên game thread
Cách kiểm tra
Kiểm tra bằng công cụ hạ tầng (không cần code game)
Tìm hiểu thêm
Vấn đề này xảy ra ở kiến trúc có nhiều thread cùng sửa dữ liệu game. Kiến trúc mà mỗi khu vực hoặc tính năng do một thread phụ trách và chỉ trao đổi bằng message thì gần như không có lock, nhưng phải cẩn thận với việc dồn việc vào một thread (quá tải khu vực chạy trên một thread). Nếu game thread phải chờ lock mà một tác vụ lưu chậm đang giữ, cả tick đó sẽ dừng lại.
Sự cố thực tế
Roblox 2021: Sự cố 73 giờ của Roblox: tranh chấp trong cụm service discovery (Consul)

Nguồn

  1. Amdahl's Law in the Multicore Era IEEE
    Bài báo IEEE Computer 2008 (bản tác giả công bố). Nếu phần không song song hóa được là 1−f thì dù tăng bao nhiêu core, tốc độ cũng không tăng quá 1/(1−f) lần (định luật Amdahl)
  2. Request scheduling Microsoft
    Grain (actor) của Orleans dùng mô hình thực thi một thread, xử lý trọn từng yêu cầu một, nên trạng thái không bị sửa đồng thời; nếu các grain chờ phản hồi của nhau thì có thể deadlock
  3. pidstat(1) — Linux manual page sysstat
    cswch/s trong -w là số context switch tự nguyện do dừng để chờ tài nguyên; -t hiển thị theo từng thread
  4. Demonstrations of offcputime, the Linux eBPF/bcc version IO Visor
    Cộng dồn thời gian thread bị dừng và rời CPU (off-CPU) theo từng call stack, -p để chỉ định tiến trình
  5. Well-known EventCounters in .NET Microsoft
    Monitor Lock Contention Count (monitor-lock-contention-count): số lần xảy ra tranh chấp khi cố lấy monitor lock
  6. .NET runtime metrics .NET
    dotnet.monitor.lock_contentions từ .NET 9: số lần xảy ra tranh chấp khi cố lấy monitor lock kể từ khi tiến trình khởi động

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

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

Nguyên nhân ở tầng khác gây cùng triệu chứng (Trễ thao tác)

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