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

คู่มือเกมแลค › L9 โปรเซสเกมฝั่งเซิร์ฟเวอร์

การแย่งล็อก Lock contention

ID สาเหตุ sp-lock · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)

เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →

ถ้าหลายเธรดรอล็อกตัวเดียวเพื่อเขียนข้อมูลเดียวกัน ต่อให้เพิ่มเธรด ก็ทำงานได้ทีละตัวเท่านั้น

ทำไม หลายเธรดใช้ข้อมูลที่ใช้ร่วมกันพร้อมกัน เช่น ตลาดประมูลหรือคลังกิลด์ → ผลคือ เธรดอื่นต้องรอจนเธรดที่ถือล็อกทำงานเสร็จ → บนหน้าจอ ช้าเฉพาะบางฟีเจอร์ ถ้าหนัก ทิกทั้งหมดก็ช้าไปด้วย

อาการ
อินพุตดีเลย์, ค้าง
ปัจจัย
การหยุดชะงัก
ใครเจอ
เฉพาะบางฟีเจอร์, ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร
ตอนคนแห่มารวมกัน
ผู้รับผิดชอบ
ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
งานฝั่งทีมพัฒนาเกม
แบ่งล็อกให้ละเอียดขึ้น, ลดงานที่ทำในล็อก, ใช้โครงสร้างแบบส่งข้อความ (กำหนดเธรดเจ้าของให้ข้อมูลแต่ละชุด แล้วให้เธรดอื่นส่งคำขอเป็นข้อความเท่านั้น)
ตัวเลขที่ควรรู้
ถ้างานในล็อกคิดเป็น 20% ของงานทั้งหมด ต่อให้เพิ่มเธรดเท่าไร throughput ก็ได้สูงสุด 5 เท่าของตอนมีเธรดเดียว ถ้า 40% จะหยุดที่ 2.5 เท่า
บนกราฟ
สูงตามจำนวนคนและโหลด · เวลาประมวลผลคำขอ, CPU และ context switch แยกตามเธรด
จุดที่ต้องดู
voluntary context switch แยกตามเธรด (cswch/s คือจำนวนครั้งที่หยุดรอทรัพยากร) จาก pidstat -w -t 1, จุดที่เธรดออกจาก CPU ไปรอ (เวลารอแยกตาม call stack) จาก bcc offcputime -p สำหรับ .NET ดูจำนวนการแย่งล็อกใน dotnet-counters (.NET 9 ขึ้นไปคือ dotnet.monitor.lock_contentions, 8 ลงไปคือ Monitor Lock Contention Count)
สัญญาณว่าใช่
โหลดเพิ่มแต่อัตราการใช้ CPU ยังต่ำ ขณะที่เวลาประมวลผลเพิ่มขึ้น เวลารอส่วนใหญ่กระจุกอยู่ใน call stack ที่พยายามถือล็อก และจำนวนการแย่งล็อกสูงขึ้นตาม
สัญญาณว่าไม่ใช่
CPU เต็ม: เป็นปัญหาปริมาณการคำนวณ (ทิกเกินงบเวลา, พื้นที่ที่รันบนเธรดเดียวโหลดเกิน) ถ้ารอการเรียก DB หรือไฟล์ น่าจะเป็น synchronous call บนเธรดเกม
วิธีตรวจ
ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม
เกิดในโครงสร้างที่หลายเธรดแก้ข้อมูลเกมร่วมกัน โครงสร้างที่ให้เธรดเดียวดูแลแต่ละพื้นที่หรือฟีเจอร์และสื่อสารกันด้วยข้อความเท่านั้นแทบไม่มีล็อก แต่ต้องระวังปัญหางานกระจุกที่เธรดเดียว (พื้นที่ที่รันบนเธรดเดียวโหลดเกิน) ถ้าเธรดเกมรอล็อกที่งานบันทึกข้อมูลซึ่งช้าถืออยู่ ทั้งทิกนั้นจะหยุดชะงัก
กรณีจริง
Roblox 2021: Roblox ล่ม 73 ชั่วโมง: การแย่งทรัพยากรในคลัสเตอร์ service discovery (Consul)

แหล่งอ้างอิง

  1. Amdahl's Law in the Multicore Era IEEE
    เปเปอร์ IEEE Computer 2008 (ฉบับที่ผู้เขียนเผยแพร่เอง) ถ้าสัดส่วนที่แบ่งทำแบบขนานไม่ได้คือ 1−f ต่อให้เพิ่มคอร์เท่าไร ความเร็วที่เพิ่มขึ้นก็ไม่เกิน 1/(1−f) (กฎของ Amdahl)
  2. Request scheduling Microsoft
    grain (actor) ของ Orleans ใช้โมเดลรันแบบเธรดเดียวที่ประมวลผลคำขอทีละรายการจนจบ จึงไม่มีการแก้สถานะพร้อมกัน, ถ้า grain รอการตอบกลับของกันและกันอาจเกิดเดดล็อก
  3. pidstat(1) — Linux manual page sysstat
    cswch/s ของ -w คือจำนวน voluntary context switch ที่หยุดเพราะรอทรัพยากร, -t แสดงแยกตามเธรด
  4. Demonstrations of offcputime, the Linux eBPF/bcc version IO Visor
    รวมเวลาที่เธรดหยุดอยู่นอก CPU (off-CPU) แยกตาม call stack, -p ระบุโปรเซส
  5. Well-known EventCounters in .NET Microsoft
    Monitor Lock Contention Count (monitor-lock-contention-count): จำนวนครั้งที่เกิดการแย่งกันตอนพยายามถือ monitor lock
  6. .NET runtime metrics .NET
    dotnet.monitor.lock_contentions ตั้งแต่ .NET 9: จำนวนครั้งที่เกิดการแย่งกันตอนพยายามถือ monitor lock นับตั้งแต่โปรเซสเริ่ม

สาเหตุที่ควรดูประกอบ

ชั้นเดียวกัน: L9 โปรเซสเกมฝั่งเซิร์ฟเวอร์

สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (อินพุตดีเลย์)

ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง