# คู่มือเกมแลค (Game Lag White Paper) > คู่มือที่อธิบาย 228 สาเหตุของแลคในเกมออนไลน์ (กระตุก, วาร์ป, ดีดกลับ, กรอเร็ว, อินพุตดีเลย์, ค้าง, หลุด ฯลฯ) โดยแบ่งเป็น 13 ชั้นตั้งแต่หน้าจอของเราไปจนถึงฐานข้อมูลบนเซิร์ฟเวอร์ และ 3 หัวข้อ (การออกแบบการซิงก์, ปัญหาที่เกิดกับบางคนเท่านั้น, การส่งซ้ำ TCP) เนื้อหาเน้นกรณีของเกม MMO แต่ส่วนใหญ่ใช้ได้กับเกมออนไลน์ทุกแนว แต่ละสาเหตุมีสามขั้น ทำไม → ผลคือ → บนหน้าจอ พร้อมอาการที่เกี่ยวข้อง, ตัวเลขที่ควรรู้, ผู้รับผิดชอบ (ทีมพัฒนาเกม/ทีมอินฟรา/ภายนอก) และงานของแต่ละทีม, รูปแบบกราฟและวิธียืนยัน รวมถึงแหล่งอ้างอิงที่เชื่อถือได้ (RFC, เอกสารทางการของเคอร์เนล OS คลาวด์ เอนจิน และ DB, งานวิจัย) แต่ละสาเหตุอ้างอิงด้วย ID (เช่น mem-gc) และมีหน้าของตัวเอง (เช่น https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-gc.html) ตัวเลขเป็นค่าตัวแทนของสภาพแวดล้อมการให้บริการทั่วไป ส่วนค่าเริ่มต้นและเวอร์ชันมีหลักฐานอยู่ในแหล่งอ้างอิงของแต่ละหน้าสาเหตุ เมื่อต้องการอ้างอิง ให้ใช้ URL ของหน้าสาเหตุ สัญญาอนุญาต MIT ต้นฉบับเป็นภาษาเกาหลี ฉบับนี้เป็นฉบับแปล: https://jungrok5.github.io/mmo-lag-anatomy/ ## เอกสาร - [เนื้อหาทั้งหมด (Markdown)](https://jungrok5.github.io/mmo-lag-anatomy/th/llms-full.txt): สาเหตุ, อาการ, ผู้รับผิดชอบ, คำศัพท์ และแหล่งอ้างอิงทั้งหมดในไฟล์เดียว - [ฉบับข้อความ](https://jungrok5.github.io/mmo-lag-anatomy/th/text.html): HTML หน้าเดียวที่มีเนื้อหาเดียวกัน อ่านได้โดยไม่ต้องใช้ JavaScript - [คู่มือเกมแลค](https://jungrok5.github.io/mmo-lag-anatomy/th/): ฉบับหลักที่มีภาพและการทดลองให้ลองปรับเอง ## สาเหตุแยกตามอาการ - [กระตุก](https://jungrok5.github.io/mmo-lag-anatomy/th/s/stutter.html): 60 สาเหตุ การเคลื่อนไหวไม่ลื่น หยุดสั้น ๆ แล้วขยับต่อ สลับกันไปเรื่อย ๆ - [วาร์ป](https://jungrok5.github.io/mmo-lag-anatomy/th/s/teleport.html): 47 สาเหตุ ตัวละครย้ายไปยังตำแหน่งที่ไกลออกไปในทีเดียว โดยไม่เห็นช่วงระหว่างทาง - [ดีดกลับ](https://jungrok5.github.io/mmo-lag-anatomy/th/s/rubber.html): 14 สาเหตุ ตัวละครของเรากำลังเดินหน้า แล้วโดนดึงกลับไปยังจุดที่เพิ่งผ่านมา - [กรอเร็ว](https://jungrok5.github.io/mmo-lag-anatomy/th/s/burst.html): 36 สาเหตุ หน้าจอที่หยุดไปกลับมาขยับอีกครั้ง แล้วการเคลื่อนไหว การโจมตี และดาเมจที่สะสมไว้ก็ผ่านไปอย่างรวดเร็วในทีเดียว - [สโลว์โมชั่น](https://jungrok5.github.io/mmo-lag-anatomy/th/s/slowmo.html): 24 สาเหตุ ทุกอย่างเคลื่อนที่ช้าลง การร่ายสกิลและการเดินของมอนสเตอร์ดูยืดยาด ขึ้นกับการออกแบบเซิร์ฟเวอร์ บางเกมความเร็วยังเท่าเดิม และไปแสดงเป็นอาการกระตุกหรือวาร์ปแทน - [อินพุตดีเลย์](https://jungrok5.github.io/mmo-lag-anatomy/th/s/delay.html): 76 สาเหตุ กดแล้วต้องรอสักพักกว่าผลจะออก ตัวภาพบนจออาจยังลื่นตามปกติ - [ค้าง](https://jungrok5.github.io/mmo-lag-anatomy/th/s/freeze.html): 67 สาเหตุ ทุกอย่างบนจอหยุดไปชั่วครู่ (0.5 วินาทีถึงหลายวินาที) แล้วกลับมาขยับต่อ - [กดไม่ติด/โรลแบ็ค](https://jungrok5.github.io/mmo-lag-anatomy/th/s/dropped.html): 36 สาเหตุ การกระทำที่ทำไปแล้วแน่ ๆ กลับไม่เกิดผล หรือผลถูกพลิกกลับหลังผ่านไปพักใหญ่ - [หลุด](https://jungrok5.github.io/mmo-lag-anatomy/th/s/disconnect.html): 51 สาเหตุ การเชื่อมต่อขาดระหว่างเล่น แล้วเด้งกลับไปหน้าล็อกอินหรือหน้าต่างเชื่อมต่อใหม่ - [เข้าเกมไม่ได้/โหลดไม่จบ](https://jungrok5.github.io/mmo-lag-anatomy/th/s/noconnect.html): 45 สาเหตุ เข้าไปในเกมไม่ได้ หรือติดอยู่ที่หน้าโหลดหรือหน้าเข้าเกม - [มองไม่เห็น/ตัวผี](https://jungrok5.github.io/mmo-lag-anatomy/th/s/invisible.html): 20 สาเหตุ NPC มอนสเตอร์ หรือผู้เล่นที่ควรจะอยู่ กลับไม่มีบนจอของเราคนเดียว หรือสิ่งที่หายไปแล้วยังเหลืออยู่บนจอของเราคนเดียว ## L1 โปรเซสเกมฝั่งไคลเอนต์ - [เฟรมไทม์พุ่ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-hitch.html): เฟรมหนึ่งใช้เวลาคำนวณนานกว่าปกติหลายเท่า ภาพบนจอจึงหยุดไปครู่หนึ่ง - [GC ฝั่งไคลเอนต์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-gc.html): ทั้งเกมหยุดระหว่างเก็บคืนหน่วยความจำที่ใช้แล้วทิ้ง (garbage) จุดสังเกตคือกระตุกเป็นจังหวะสม่ำเสมอ - [โหลดแบบ synchronous และคอมไพล์ shader บนเมนเธรด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-sync-load.html): เกมหยุดเพราะต้องอ่านไฟล์และสร้าง shader ก่อนวาดพื้นที่, มอนสเตอร์ หรือเอฟเฟกต์ที่เพิ่งเห็นเป็นครั้งแรก - [สตอเรจช้าจนสตรีมแอสเซ็ตไม่ทัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-asset-stream.html): บนสตอเรจช้าอย่าง HDD การอ่าน texture และโมเดลของโอเพนเวิลด์ตามการเคลื่อนที่ไม่ทัน เอนทิตีจึงโผล่ช้า หรือเกมกระตุกระหว่างรออ่านข้อมูล - [ภาระการเรนเดอร์ตัวละครจำนวนมาก](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-crowd.html): เมื่อคนหลายร้อยคนเข้ามาอยู่ในจอเดียว เช่น ศึกชิงปราสาทหรือเวิลด์บอส ลำพังต้นทุนการวาดภาพก็รับไม่ไหวแล้ว - [คอขวดการประมวลผลแพ็กเก็ตบนเมนเธรด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-net-mainthread.html): ถ้าประมวลผลแพ็กเก็ตที่รับมาได้แค่จำนวนที่กำหนดในแต่ละเฟรม แพ็กเก็ตที่ทะลักเข้ามาจะถูกเลื่อนไปเฟรมถัดไปเรื่อย ๆ - [ไม่มี interpolation buffer หรือสั้นเกินไป](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-no-buffer.html): ถ้าวาดทันทีที่ได้รับแพ็กเก็ตจากเซิร์ฟเวอร์ จิตเตอร์ (ช่วงเวลาที่แพ็กเก็ตมาถึงไม่สม่ำเสมอ) จะแสดงออกมาบนจอตรง ๆ - [extrapolation มากเกินไป (dead reckoning)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-extrap.html): ระหว่างที่แพ็กเก็ตไม่มา เกมแสดงตัวละครให้เคลื่อนที่ต่อด้วยความเร็วล่าสุด แล้วดึงกลับเมื่อรู้ว่าผิด - [client-side prediction ไม่ตรงกับเซิร์ฟเวอร์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-predict.html): ไคลเอนต์ของเราแสดงการเคลื่อนที่ไปก่อน แต่ถ้าเซิร์ฟเวอร์คำนวณออกมาต่างกัน ตัวละครของเราจะโดนดึงกลับ - [fixed timestep ไล่ตามไม่ทันจนบานปลาย](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-fixed-step.html): หลังหยุดไปครั้งหนึ่ง เกมเร่งคำนวณส่วนที่ตามหลังรวดเดียว แล้วการคำนวณนั้นเองก็ทำให้ตามหลังอีก - [ซิงก์นาฬิกาคลาดเคลื่อน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-clock.html): ถ้าเวลาเซิร์ฟเวอร์ที่ไคลเอนต์ประมาณไว้ผิด จังหวะ interpolation และการตัดสินคูลดาวน์จะคลาดกัน - [เวลาแบบ float สูญเสียความแม่นยำ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-float-time.html): ถ้าเก็บเวลาในเกมเป็นทศนิยมความแม่นยำต่ำ (float) ยิ่งเปิดเกมไว้นาน ความละเอียดของเวลา (ผลต่างของเวลาที่เล็กที่สุดที่แยกได้) ก็ยิ่งลดลง การเคลื่อนไหวและเอฟเฟกต์จึงสั่น - [V-Sync และคิวเรนเดอร์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-vsync.html): ระหว่างที่ GPU เก็บเฟรมที่วาดเสร็จไว้ในคิวหลายเฟรม แล้วค่อยส่งออกตามรอบของจอ อินพุตจะช้าลง - [หน่วยความจำรั่วฝั่งไคลเอนต์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-leak.html): ยิ่งเปิดไว้นาน หน่วยความจำยิ่งเพิ่ม เกมช้าลงเรื่อย ๆ แล้วสุดท้ายก็ถูกบังคับปิด - [ไคลเอนต์แครช](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-crash.html): เกมปิดตัวลงเพราะข้อผิดพลาดที่ไม่ได้จัดการ ผู้เล่นเห็นเหมือนหลุด แต่เซิร์ฟเวอร์ปกติ - [การตรวจของโมดูลความปลอดภัยเกม (anti-cheat)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/cg-anticheat.html): โมดูลความปลอดภัยที่ทำงานคู่กับเกมเพื่อกันโปรโกงจะตรวจสอบเป็นระยะ ถ้าการตรวจหนัก หรือ heartbeat (สัญญาณยืนยันว่ายังทำงานอยู่ที่ส่งเป็นระยะ) ที่รับส่งกับเซิร์ฟเวอร์ความปลอดภัยมาช้า เกมจะกระตุกหรือหลุด ## L2 OS และอุปกรณ์ฝั่งไคลเอนต์ - [โปรเซสเบื้องหลังแย่ง CPU](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-background.html): เมื่อการสแกนของแอนตี้ไวรัส, Windows Update, โปรแกรมสตรีม หรือวิดีโอในเบราว์เซอร์ยึดคอร์ไว้ เธรดเกมจะไม่ได้รับ CPU และต้องรอ - [โหมดประหยัดพลังงานและ thermal throttling](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-power.html): โหมดแบตเตอรี่ของโน้ตบุ๊ก, โหมดประหยัดพลังงานของมือถือ และความร้อนของเครื่อง ทำให้ CPU และ GPU ช้าลง จุดสังเกตของความร้อนคือช่วงแรกปกติดี แล้วค่อยช้าลงหลังเล่นไปสักพัก - [ความละเอียดของตัวจับเวลา](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-timer.html): ตัวจับเวลาเริ่มต้นของ Windows ทำงานเป็นหน่วย 15.6 ms การ “พักแค่ 1 ms” จึงกลายเป็นการรอจนถึงรอบตัวจับเวลาถัดไป นานสุดถึง 15.6 ms - [สลับแอปมือถือไปเบื้องหลัง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-mobile-bg.html): ถ้าย่อแอปลงไปแป๊บเดียวเพื่อดูแจ้งเตือน OS จะพักการทำงาน (suspend) ของแอปภายในไม่กี่วินาที และระหว่างนั้นเซิร์ฟเวอร์จะตัดการเชื่อมต่อของเรา - [สลับ Wi-Fi ↔ LTE/5G](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-netswitch.html): เมื่อเดินออกจากบ้านแล้ว Wi-Fi หลุดและเปลี่ยนไปใช้ LTE หรือ 5G IP address ของเราจะเปลี่ยน การเชื่อมต่อเดิมจึงใช้ไม่ได้ - [โปรแกรมความปลอดภัยตรวจแพ็กเก็ต](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-security.html): ถ้าแอนตี้ไวรัสหรือไฟร์วอลล์ตรวจทุกแพ็กเก็ต ความหน่วงจะเพิ่มขึ้น และถ้าตรวจเข้มเกินไปก็อาจเข้าใจผิดว่าเกมเป็นการโจมตีแล้วบล็อก - [receive buffer ล้น](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-rcvbuf.html): ถ้าเกมยุ่งจนดึงแพ็กเก็ตออกจากซ็อกเก็ต (อินเทอร์เฟซรับส่งข้อมูลเครือข่ายที่ OS จัดให้) ช้า บัฟเฟอร์ของ OS จะล้น - [หน่วยความจำฝั่งไคลเอนต์ไม่พอและ swap](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-swap.html): ถ้าเปิดแท็บเบราว์เซอร์หลายสิบแท็บพร้อมกับเกม OS จะย้ายหน่วยความจำบางส่วนของเกมไปไว้บนดิสก์ - [หน่วยความจำกราฟิก (VRAM) ไม่พอ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-vram.html): ถ้าหน่วยความจำที่ตัวเลือกกราฟิกต้องการมากกว่าหน่วยความจำของการ์ดจอ OS จะย้าย texture ไปไว้ในหน่วยความจำของ PC แล้วดึงกลับมาใหม่ ภาพจึงกระตุก - [การสแกน Wi-Fi เบื้องหลัง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-wifi-scan.html): ระหว่างที่ OS สลับช่องสัญญาณไปมาเป็นระยะเพื่อหา Wi-Fi รอบตัว การรับส่งข้อมูลจะหยุดไปครู่หนึ่ง - [โหมดประหยัดพลังงานของ NIC และปัญหาไดรเวอร์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-driver.html): ถ้าการ์ด LAN หรือชิป Wi-Fi เข้าสู่โหมดประหยัดพลังงานระหว่างแพ็กเก็ต จะต้องใช้เวลากว่าจะกลับมาทำงาน - [แอปอื่นในเครื่องเดียวกันแย่งแบนด์วิดท์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-other-apps.html): ถ้าการซิงก์ไฟล์ขึ้นคลาวด์, การดาวน์โหลดไฟล์ใหญ่ หรือแพตช์เกมกำลังทำงานบน PC เครื่องเดียวกัน แพ็กเก็ตเกมจะต้องรอในคิว - [จำกัดการประมวลผลเมื่อย่อหรือสลับหน้าต่าง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-unfocused.html): เมื่อไปดูหน้าต่างอื่นหรือย่อเกม ตัวเกมและ Windows จะลดความเร็วการทำงานของเกมเพื่อประหยัดไฟ พอกลับมา แพ็กเก็ตที่กองรอจะทะลักเข้ามา หรือหลุดไปแล้ว - [โปรแกรมโอเวอร์เลย์รบกวน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-overlay.html): โปรแกรมแชต, launcher, โปรแกรมอัดจอ และโปรแกรมแสดง FPS จะแทรกเข้าไปในขั้นตอนการเรนเดอร์ของเกม (hooking) เพื่อวาด UI ของตัวเองทับบนจอเกม งานในแต่ละเฟรมจึงเพิ่มขึ้น และบางครั้งก็ชนกับเกมจนภาพหยุดแวบหรือเกมถูกบังคับปิด - [ดีเลย์จากจอ, อุปกรณ์อินพุต และ frame generation](https://jungrok5.github.io/mmo-lag-anatomy/th/c/co-display-input.html): ถ้าปิงปกติแต่การควบคุมรู้สึกหนืด อาจเป็นเพราะการประมวลผลภาพของทีวี, คอนโทรลเลอร์ไร้สาย หรือ frame generation กำลังเพิ่มดีเลย์ระหว่างอินพุตกับภาพบนจอ ## L3 เครือข่ายในบ้าน - [Wi-Fi ถูกรบกวนหรือสัญญาณอ่อน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-wifi.html): ถ้าสัญญาณอ่อนหรือถูกรบกวน ช่วงไร้สายต้องส่งซ้ำหลายรอบ แพ็กเก็ตจึงมาถึงไม่สม่ำเสมอ - [ช่องสัญญาณ Wi-Fi แออัด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-channel.html): ในที่ที่มีเราเตอร์หลายสิบตัวอย่างคอนโดหรืออพาร์ตเมนต์ ต้องแบ่งกันใช้ช่องสัญญาณเดียวกัน จึงต้องรอโอกาสส่ง - [bufferbloat (คิวในเราเตอร์)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-bufferbloat.html): เมื่อมีคนในบ้านอัปโหลดวิดีโอหรือดาวน์โหลดไฟล์ใหญ่ แพ็กเก็ตจะกองอยู่ในคิวของเราเตอร์ยาวเป็นหลายร้อย ms และแพ็กเก็ตเกมก็ต้องรอต่อท้าย - [NAT mapping หมดอายุ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-nat.html): เราเตอร์จะลบการเชื่อมต่อที่ idle (ไม่มีแพ็กเก็ตวิ่งมาสักพัก) ออกจากตาราง NAT นี่คือสาเหตุที่พบบ่อยของอาการหลุดตอนที่เพิ่งขยับหลังจากอยู่เฉย ๆ - [เราเตอร์สเปกไม่พอหรือร้อนเกิน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-router.html): เมื่ออุปกรณ์หลายสิบเครื่องและการเชื่อมต่อหลายพันรายการมารวมที่เราเตอร์ราคาถูก ตัวเราเตอร์เองจะประมวลผลไม่ไหว - [handover ระหว่างเสาสัญญาณ (ขณะเดินทาง)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-handover.html): เมื่อเดินทางด้วยรถเมล์หรือรถไฟใต้ดิน การสื่อสารจะขาดช่วงระหว่างที่เปลี่ยนเสาสัญญาณ - [ดีเลย์จากการเปลี่ยนสถานะ RRC (โหมดประหยัดพลังงานของวิทยุมือถือ)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-rrc.html): ถ้าไม่มีการสื่อสารสักพัก มือถือจะลดการเชื่อมต่อวิทยุลงเป็นสถานะพลังงานต่ำ และเมื่อมีแพ็กเก็ตถัดไปต้องยกกลับขึ้นมาใหม่ จึงช้าลง - [สัญญาณมือถืออ่อนหรืออยู่ในจุดอับสัญญาณ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-weak-cell.html): ในลิฟต์, ชั้นใต้ดิน หรือด้านในอาคาร การส่งซ้ำจะเพิ่มขึ้น ความเร็วลดลง และสุดท้ายก็หลุด - [สลับ 5G↔LTE บ่อย (บริเวณขอบพื้นที่ 5G)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-5g-flip.html): ในอาคารที่สัญญาณ 5G อ่อน หรือบริเวณขอบพื้นที่ 5G มือถือจะสลับไปมาระหว่าง 5G กับ LTE บ่อย และทุกครั้งที่สลับ ปิงจะพุ่งหรือการสื่อสารขาดไปครู่หนึ่ง - [ข้อจำกัดของ Wi-Fi สาธารณะและเครือข่ายบริษัท](https://jungrok5.github.io/mmo-lag-anatomy/th/c/hn-captive.html): หน้าล็อกอิน Wi-Fi ของร้านกาแฟหรือไฟร์วอลล์ของบริษัทบล็อกการเชื่อมต่อของเกม ## L4 เส้นทางอินเทอร์เน็ต - [ความหน่วงในการแพร่สัญญาณ (ระยะทางจริง)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-distance.html): แม้แต่แสงในสายไฟเบอร์ก็เดินทางได้แค่ประมาณ 200,000 กิโลเมตรใน 1 วินาที เซิร์ฟเวอร์ที่อยู่ไกลจะดีแค่ไหนก็ยังช้า - [อินเทอร์เน็ตดาวเทียม (วงโคจรต่ำ/ค้างฟ้า)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-satellite.html): อินเทอร์เน็ตดาวเทียมต้องส่งสัญญาณขึ้นไปในอวกาศแล้วกลับลงมา ดาวเทียมวงโคจรค้างฟ้าแค่ช่วงขึ้นลงนี้ก็ใช้เวลาไปกลับเกิน 0.5 วินาทีแล้ว ส่วนดาวเทียมวงโคจรต่ำอย่าง Starlink ปกติเร็ว แต่ตอนที่ระบบจัดเส้นทางใหม่ ความหน่วงจะแกว่งและบางครั้งขาดไปชั่วครู่ - [เส้นทางวิ่งอ้อม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-routing.html): เพราะสัญญาการเชื่อมต่อระหว่าง ISP แม้เซิร์ฟเวอร์จะอยู่ใกล้ แพ็กเก็ตก็ยังวิ่งอ้อมไปทางไกล - [จุด peering แออัดช่วงพีค](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-peak.html): ช่วงหัวค่ำราว 21:00–23:00 ทราฟฟิกวิดีโอพุ่งขึ้นมาก จุดเชื่อมต่อระหว่าง ISP (peering) จึงมักแออัด - [เคเบิลใต้น้ำ/วงจรต่างประเทศขัดข้อง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-cable.html): เมื่อเคเบิลใต้น้ำขาด ทราฟฟิกต้องอ้อมไปเส้นทางไกลหลายสัปดาห์ (นานสุดหลายเดือน) จนกว่าจะซ่อมเสร็จ และวงจรที่เหลืออยู่ก็แออัด - [เส้นทาง BGP เปลี่ยนและ converge ใหม่](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-bgp.html): เมื่อข้อมูลเส้นทางของอินเทอร์เน็ตเปลี่ยน แพ็กเก็ตจะหายในช่วงไม่กี่วินาทีถึงหลายสิบวินาที (บางกรณีหลายนาที) ที่เส้นทางกำลัง converge ใหม่ - [เส้นทาง ECMP เส้นหนึ่งเสีย](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-ecmp.html): ISP และดาต้าเซ็นเตอร์มีหลายเส้นทางไปยังปลายทางเดียวกัน และกำหนดเส้นทางหนึ่งเส้นให้แต่ละการเชื่อมต่อ ถ้าเสียแค่เส้นเดียว คนที่ถูกจัดให้ใช้เส้นนั้นจะแลคอยู่ตลอด - [ISP จำกัดความเร็วและจัดการทราฟฟิก](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-shaping.html): ในแพ็กเกจที่ใช้ดาต้าเกินโควตาแล้ว หรือแพ็กเกจที่มีการจัดการทราฟฟิกบางประเภท แพ็กเก็ตจะถูกหน่วงหรือถูกทิ้ง - [การจำกัด UDP และตรวจแพ็กเก็ตระดับประเทศหรือ ISP](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-udp-block.html): บางเครือข่ายบล็อก IP หรือพอร์ต UDP บางตัว หรือจำกัดความเร็ว UDP และอุปกรณ์ตรวจแพ็กเก็ตจะกรองโปรโตคอลที่ไม่รู้จักทิ้ง เกมที่สื่อสารด้วย UDP จึงเชื่อมต่อในเครือข่ายนั้นไม่ได้หรือหลุดบ่อย - [คุณภาพสายเน็ตแย่](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-line.html): ขั้วต่อหลวม สายเก่า หรือโมเด็มผิดปกติ ทำให้แพ็กเก็ตหายอย่างต่อเนื่องและเน็ตขาดเป็นระยะ - [DNS ขัดข้อง/ช้า](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-dns.html): ถ้า DNS ซึ่งแปลงชื่อเซิร์ฟเวอร์เป็น IP ช้าหรือล้มเหลว เกมจะหาเซิร์ฟเวอร์ล็อกอินหรือเซิร์ฟเวอร์แพตช์ไม่เจอ - [ลิงก์ที่ใช้ร่วมกันเต็มเพราะ DDoS](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-ddos-path.html): การโจมตีปริมาณมหาศาลที่พุ่งเป้ามาที่บริษัทเกม หรือที่อื่นในเครือข่ายเดียวกัน ทำให้ลิงก์ที่ใช้ร่วมกันเต็ม - [IP ที่ ISP ให้ใช้ร่วมกัน (CGNAT)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-cgnat.html): เครือข่ายมือถือและ ISP บางรายให้ผู้ใช้บริการหลายรายใช้ IP เดียวร่วมกัน และลบ mapping ของการเชื่อมต่อที่ idle ภายในเวลาสั้น ๆ - [เชื่อมต่อผ่าน VPN/โปรแกรมลดปิง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/isp-vpn.html): เมื่อเปิด VPN หรือโปรแกรมลดปิง แพ็กเก็ตจะวิ่งผ่านเซิร์ฟเวอร์ตัวกลาง (relay) ของบริษัทนั้น ถ้าเซิร์ฟเวอร์ตัวกลางอยู่ไกลหรือแออัด ก็กลับยิ่งช้าลง ## L5 อุปกรณ์เครือข่ายในดาต้าเซ็นเตอร์ - [ตารางเซสชันของไฟร์วอลล์เต็ม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-firewall.html): ไฟร์วอลล์บันทึกทุกการเชื่อมต่อที่ปล่อยผ่านไว้ในตารางเซสชันเพื่อติดตาม เมื่อตารางเต็มก็รับการเชื่อมต่อใหม่ไม่ได้ - [การอ้อมผ่านระบบป้องกัน DDoS และ false positive](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-ddos.html): เมื่อเบี่ยงทราฟฟิกไป scrubbing center เพื่อกันการโจมตี เส้นทางจะยาวขึ้น และบางครั้งระบบเข้าใจผิดว่าผู้เล่นปกติเป็นการโจมตีแล้วบล็อก - [idle timeout ของโหลดบาลานเซอร์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-lb-idle.html): โหลดบาลานเซอร์ลบการเชื่อมต่อที่ idle ทิ้งหลังผ่านไประยะหนึ่ง ฝั่งเกมยังคิดว่าการเชื่อมต่อยังอยู่ จนกระทั่งหลุด - [connection tracking ของ security group บนคลาวด์หมดอายุ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-cloud-conntrack.html): ไฟร์วอลล์ที่ผูกกับเซิร์ฟเวอร์บนคลาวด์ (security group) ก็ติดตามการเชื่อมต่อเช่นกัน และรายการที่ติดตามของการเชื่อมต่อที่ idle จะหมดอายุหลังเวลาที่กำหนด แม้เป็นเซิร์ฟเวอร์ที่ผู้เล่นเชื่อมต่อตรงโดยไม่มีโหลดบาลานเซอร์ ผู้เล่นที่อยู่เฉย ๆ ก็อาจหลุดได้ - [ขีดจำกัดการเชื่อมต่อ/พอร์ตของ NAT gateway บนคลาวด์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-nat-gateway.html): การเชื่อมต่อที่เซิร์ฟเวอร์ใน private subnet ออกไปภายนอก (ระบบยืนยันตัวตนของแพลตฟอร์ม, ระบบชำระเงิน, API ภายนอก) จะผ่าน NAT gateway ซึ่งแปลง IP และพอร์ตก่อนส่งออก ถ้าการเชื่อมต่อพร้อมกันไปยังปลายทางเดียวกันเกินขีดจำกัดพอร์ตของ gateway การเชื่อมต่อใหม่จะล้มเหลว - [โหลดบาลานเซอร์กระจายไม่เท่ากัน/health check ตัดสินผิด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-lb-imbalance.html): การเชื่อมต่อไปกองที่เซิร์ฟเวอร์เครื่องเดียว หรือยังส่งคนไปเซิร์ฟเวอร์ที่ตายแล้วอยู่เรื่อย ๆ - [microburst ที่สวิตช์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-microburst.html): ถ้าเซิร์ฟเวอร์หลายเครื่องส่งแพ็กเก็ตถึงผู้เล่นหลายพันคนพร้อมกันในชั่วขณะเดียว บัฟเฟอร์ขนาดเล็กของพอร์ตสวิตช์ที่ทราฟฟิกนั้นไหลมารวมกันจะล้นภายในไม่ถึง 1 ms - [ลิงก์ของดาต้าเซ็นเตอร์เต็ม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-uplink.html): ถ้าการแจกจ่ายแพตช์ การส่ง log หรือการสำรองข้อมูล ใช้ลิงก์เดียวกับเกม ลิงก์จะเต็ม - [การ failover ของอุปกรณ์เครือข่าย](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-failover.html): ระหว่างไม่กี่วินาทีที่เราเตอร์หรือไฟร์วอลล์ตัวหนึ่งเสียแล้วสลับไปใช้อุปกรณ์สำรอง (failover) ทุกคนจะค้างพร้อมกัน - [สายเสีย/พอร์ตมี error](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-bad-cable.html): ถ้าโมดูลออปติกหรือสายเสีย แพ็กเก็ตที่ผ่านเส้นทางนั้นจะเสียหายในสัดส่วนคงที่ - [MTU ไม่ตรงกัน (เฉพาะแพ็กเก็ตใหญ่ที่หาย)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dc-mtu.html): ถ้า MTU (ขนาดที่ส่งได้ในครั้งเดียว) ของช่วงกลางทางลดลง แต่ข้อความแจ้งว่าขนาดเกินถูกบล็อก แพ็กเก็ตใหญ่จะหายไปเรื่อย ๆ ## L6 การ์ดเครือข่ายของเซิร์ฟเวอร์ - [อินเทอร์รัปต์ของ NIC กระจุกที่คอร์เดียว](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-irq.html): ถ้า NIC ส่งอินเทอร์รัปต์แจ้งว่าแพ็กเก็ตมาถึงไปที่คอร์ CPU เพียงคอร์เดียว คอร์นั้นจะกลายเป็นคอขวด - [ring buffer ไม่พอ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-ring.html): ถ้า ring buffer ที่ NIC ใช้พักแพ็กเก็ตไว้ชั่วคราวมีขนาดเล็ก เมื่อแพ็กเก็ตทะลักเข้ามาในชั่วขณะ บัฟเฟอร์จะล้นและแพ็กเก็ตถูกทิ้ง - [interrupt coalescing มากเกินไป](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-coalesce.html): การรวบแพ็กเก็ตไว้แล้วแจ้งทีเดียวช่วยลดภาระ CPU แต่ก็ทำให้ช้าลงตามเวลาที่ใช้รวบ - [เกินขีดจำกัด PPS ของคลาวด์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-cloud-pps.html): เซิร์ฟเวอร์บนคลาวด์แต่ละประเภทมีขีดจำกัดจำนวนแพ็กเก็ตต่อวินาทีและแบนด์วิดท์ ถ้าเกินจะถูกทิ้งเงียบ ๆ - [แบนด์วิดท์ NIC เต็ม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-saturate.html): ถ้าใช้การ์ด 1 Gbps หรือ 10 Gbps จนถึงขีดจำกัด transmit queue จะยาวขึ้น และสุดท้ายแพ็กเก็ตจะถูกทิ้ง - [โอเวอร์เฮดจาก virtualization/noisy neighbor](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-noisy.html): ถ้า VM อื่นที่อยู่บนเครื่องจริงเครื่องเดียวกันใช้เครือข่ายหรือ CPU มาก การประมวลผลของเซิร์ฟเวอร์เราจะถูกเลื่อนออกไปอย่างไม่สม่ำเสมอ - [การซ่อมบำรุงโฮสต์คลาวด์/live migration](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-host-maintenance.html): เมื่อผู้ให้บริการคลาวด์ซ่อมบำรุงเครื่องจริง (โฮสต์) จะย้าย VM ไปโฮสต์อื่น (live migration) หรือหยุด VM ชั่วคราว ระหว่างนั้นทั้งเซิร์ฟเวอร์จะหยุด และถ้าหยุดนาน การเชื่อมต่อจะขาด - [ปัญหาไดรเวอร์/เฟิร์มแวร์ของ NIC](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-reset.html): ระหว่างที่การ์ดหยุดแล้วเริ่มใหม่เพราะบั๊กของไดรเวอร์หรือฟีเจอร์ทำงานผิดพลาด การรับส่งทั้งหมดจะขาด - [ดีเลย์จากการรอรวมแพ็กเก็ตของ GRO/LRO](https://jungrok5.github.io/mmo-lag-anatomy/th/c/nic-offload.html): เป็นฟีเจอร์ที่รวมหลายแพ็กเก็ตเป็นก้อนเดียวเพื่อลดภาระ CPU บางการตั้งค่าทำให้แพ็กเก็ตเกมขนาดเล็กต้องรอแพ็กเก็ตถัดไปที่จะรวมด้วยสักครู่ ## L7 OS ของเซิร์ฟเวอร์ (เคอร์เนล) - [คิวรอเชื่อมต่อ (backlog) ล้น](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-backlog.html): ทันทีหลังปิดปรับปรุง ถ้าผู้เล่นหลายหมื่นคนเชื่อมต่อพร้อมกัน คิวรอเชื่อมต่อ (backlog) ของเคอร์เนลจะล้น และความพยายามเชื่อมต่อจะถูกทิ้ง - [ขีดจำกัด file descriptor](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-fd.html): ทุกการเชื่อมต่อต้องใช้ file descriptor (fd คือหมายเลขที่ OS กำหนดให้ไฟล์หรือซ็อกเก็ตที่เปิดอยู่) แต่จำนวน fd ที่หนึ่งโปรเซสเปิดได้มีจำกัด - [บัฟเฟอร์ซ็อกเก็ตของเคอร์เนลไม่พอ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-sockbuf.html): ถ้าบัฟเฟอร์ส่งและรับเล็ก เมื่อทราฟฟิกมาเป็น burst แพ็กเก็ตที่รับทาง UDP จะถูกทิ้ง ส่วนการส่งทาง TCP จะติดเพราะบัฟเฟอร์ไม่มีที่ว่าง - [เธรดมากเกินไปและ context switch](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-context.html): ถ้ารันเธรดมากกว่าจำนวนคอร์มาก ๆ OS จะเสีย CPU ไปกับการสลับให้เธรดผลัดกันทำงานอย่างเดียว - [CPU steal (VM)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-steal.html): ระหว่างที่เครื่องจริง (ไฮเปอร์ไวเซอร์) ยก CPU time ของ VM ไปให้ VM ตัวอื่นชั่วครู่ (CPU steal) เซิร์ฟเวอร์เกมจะหยุดชะงัก - [CPU throttling ของคอนเทนเนอร์ (CFS quota)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-cpu-quota.html): ถ้าตั้งขีดจำกัด CPU ให้คอนเทนเนอร์ เมื่อใช้โควตาหมดภายในรอบที่กำหนด (ปกติ 100 ms) คอนเทนเนอร์จะถูกบังคับหยุดตลอดเวลาที่เหลือของรอบนั้น (throttling) - [ความหน่วงพุ่งจากการจัดการพลังงานของเซิร์ฟเวอร์ (C-state/การปรับความถี่)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-cstate.html): คอร์ CPU ที่ว่างจะเข้าโหมดประหยัดพลังงานระดับลึก (C-state) และลดความถี่ลงเพื่อประหยัดไฟ เมื่อแพ็กเก็ตหรือตัวจับเวลามาถึง ต้องใช้เวลาตื่นและเพิ่มความถี่ การประมวลผลแพ็กเก็ตเล็ก ๆ จึงมีดีเลย์เพิ่มขึ้น - [OOM killer](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-oom.html): เมื่อหน่วยความจำหมด Linux จะเลือกโปรเซสที่ใช้หน่วยความจำมากที่สุดแล้วบังคับปิด ซึ่งส่วนใหญ่คือเซิร์ฟเวอร์เกม - [หยุดชะงักจาก memory reclaim และ compaction](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-reclaim.html): โปรเซสจะหยุดชะงักระหว่างที่ OS ทำ compaction หน่วยความจำเพื่อสร้างเพจขนาดใหญ่ (huge page) หรือเรียกคืนหน่วยความจำให้ว่าง (reclaim) - [นาฬิการะบบกระโดด (NTP step)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-timejump.html): ถ้านาฬิกาของเซิร์ฟเวอร์ถูกปรับไปข้างหน้าหรือถอยหลังหลายวินาทีในครั้งเดียว ตัวจับเวลาที่อิงนาฬิการะบบจะทำงานพร้อมกันรวดเดียวหรือหยุดไป - [งานตามกำหนดเวลา (scheduled job)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-cron.html): งานบีบอัด log, การสำรองข้อมูล และการสแกนความปลอดภัยที่รันเวลาเดิมทุกวันจะกิน CPU และดิสก์ - [ประสิทธิภาพเปลี่ยนไปหลังอัปเดต OS/เคอร์เนล/ไดรเวอร์/เฟิร์มแวร์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-os-update.html): โค้ดเกมเหมือนเดิม แต่เซิร์ฟเวอร์ช้าลงตั้งแต่อัปเดต OS, เคอร์เนล, ไดรเวอร์ หรือเฟิร์มแวร์ การอัปเดตอาจเปลี่ยนค่าเริ่มต้น, scheduler, การป้องกันช่องโหว่ CPU (mitigations) และพฤติกรรมของไดรเวอร์ - [ตาราง conntrack ของเซิร์ฟเวอร์เต็ม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-conntrack.html): เมื่อตาราง connection tracking (conntrack) ที่ไฟร์วอลล์ของ Linux ใช้บันทึกทุกการเชื่อมต่อแตะขีดจำกัด แพ็กเก็ตใหม่จะถูกทิ้ง - [ephemeral port หมดในการเชื่อมต่อระหว่างเซิร์ฟเวอร์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/so-ports.html): ถ้าเซิร์ฟเวอร์เกมเปิดและปิดการเชื่อมต่อสั้น ๆ ไปยัง DB หรือเซิร์ฟเวอร์อื่นบ่อย ๆ การเชื่อมต่อที่ปิดแล้วจะยังถือครองพอร์ตอยู่สักพัก จนเปิดการเชื่อมต่อใหม่ไม่ได้ ## L8 ซ็อกเก็ตและโปรโตคอล - [TCP HOL blocking](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-hol.html): เพื่อรักษาลำดับข้อมูล TCP จะไม่ส่งแพ็กเก็ตที่มาถึงทีหลังให้เกม จนกว่าจะได้รับแพ็กเก็ตที่หายไปหนึ่งตัวนั้นอีกครั้ง - [TCP RTO และ exponential backoff](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-rto.html): ทุกครั้งที่การส่งซ้ำล้มเหลวอีก เวลารอจะเพิ่มเป็นสองเท่า การเชื่อมต่อที่ขาดไปแป๊บเดียวจึงกลายเป็นการหยุดยาว - [อัลกอริทึม Nagle + delayed ACK](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-nagle.html): อัลกอริทึม Nagle ที่รวบรวมแพ็กเก็ตเล็กก่อนส่ง กับ delayed ACK ที่ส่ง ACK ช้า ทำงานประกบกัน ทุกครั้งที่เขียนข้อความแบ่งเป็นหลายส่วนจึงดีเลย์ 40–200 ms - [การส่งแบบ blocking เพราะไคลเอนต์ช้า](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-block-send.html): ถ้า send buffer ของผู้เล่นคนหนึ่งที่เน็ตช้าเต็ม แล้วเซิร์ฟเวอร์ส่งแบบ blocking (การส่งที่ฟังก์ชันจะไม่คืนค่าจนกว่าบัฟเฟอร์จะมีที่ว่าง) เธรดของเซิร์ฟเวอร์จะต้องรอผู้เล่นคนนั้นคนเดียว - [นโยบายจัดการไคลเอนต์ที่ช้า (slow consumer)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-slow-client.html): เมื่อข้อมูลที่ต้องส่งให้ไคลเอนต์ใดกองสะสมเรื่อย ๆ เซิร์ฟเวอร์จะทิ้งอัปเดตเก่าหรือตัดการเชื่อมต่อ - [keepalive ค่าเริ่มต้น 2 ชั่วโมง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-keepalive.html): ถ้าอีกฝั่งหายไปโดยไม่ส่งสัญญาณปิด TCP จะรู้ตัวหลังผ่านไปนานมาก keepalive (ฟีเจอร์ของ TCP ที่ตรวจว่าการเชื่อมต่อที่ idle ยังอยู่หรือไม่) ปิดไว้เป็นค่าเริ่มต้น และต่อให้เปิด ก็ต้อง idle ครบ 2 ชั่วโมงก่อนจึงเริ่มตรวจ - [IP fragmentation ของแพ็กเก็ต UDP](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-fragment.html): แพ็กเก็ต UDP ที่ใหญ่กว่า MTU (ขนาดสูงสุดที่ส่งได้ในครั้งเดียว) จะถูกแบ่งเป็นชิ้น (fragmentation) ที่ชั้น IP และถ้า fragment หายไปแค่ชิ้นเดียว ทั้งแพ็กเก็ตจะถูกทิ้ง - [การตั้งค่าการส่งซ้ำของ reliable UDP](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-reliable-udp.html): ถ้ากฎการส่งซ้ำที่สร้างเองบน UDP ระมัดระวังเกินไป การกู้คืนจะช้า ถ้าดุดันเกินไปก็จะยิ่งทำให้เน็ตอุดตัน - [slow start หลัง idle](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-slowstart.html): เมื่อการเชื่อมต่อ idle ไปสักพัก TCP จะลด congestion window (ปริมาณที่ส่งได้ในครั้งเดียว) กลับลงมา พอต้องส่งข้อมูลก้อนใหญ่ขึ้นมากะทันหันจึงต้องแบ่งส่งหลายรอบ - [อัตราการส่งดิ่งลงเพราะ congestion control](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-congestion.html): TCP มองว่าแพ็กเก็ตหายคือสัญญาณของความแออัด จึงลดอัตราการส่งลง 30–50% และตอบสนองแบบเดียวกันแม้แพ็กเก็ตหายเพราะ Wi-Fi - [ข้อมูลสุดท้ายหายเพราะปิดการเชื่อมต่อแบบบังคับ (RST)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-linger.html): ถ้าเซิร์ฟเวอร์ตัดการเชื่อมต่อแบบกะทันหัน ข้อความแจ้งสุดท้ายหรือสัญญาณว่าบันทึกข้อมูลเสร็จที่ส่งออกไปจะหายไป - [โครงสร้างแบบ blocking I/O](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-blocking-io.html): โครงสร้างที่เธรดทำอย่างอื่นไม่ได้ระหว่างรอซ็อกเก็ตตัวเดียว จะทำให้ทั้งระบบช้าลงเมื่อคนเพิ่มขึ้น - [การกระจายของ SO_REUSEPORT ไม่สมดุล](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-reuseport.html): เมื่อหลายโปรเซสแบ่งกันรับพอร์ตเดียวกัน เคอร์เนลจะกำหนดโปรเซสที่รับแต่ละการเชื่อมต่อด้วย hash ของที่อยู่ และไม่เปลี่ยนอีก ถ้าโปรเซสตัวใดหยุด เฉพาะคนที่ถูกจัดให้โปรเซสนั้นจะต้องรอ - [ข้อผิดพลาด WSAECONNRESET บนซ็อกเก็ต UDP ของ Windows](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sk-udp-connreset.html): ถ้าเซิร์ฟเวอร์ Windows ส่ง UDP ไปหาไคลเอนต์ที่ออกไปแล้ว จะได้ข้อความแจ้ง “ไม่พบพอร์ต” (ICMP) กลับมา ข้อความนั้นทำให้การเรียกรับครั้งถัดไปจบด้วยข้อผิดพลาด และถ้าโค้ดเซิร์ฟเวอร์ถือว่าข้อผิดพลาดนี้คือซ็อกเก็ตเสีย ทุกคนที่ใช้ซ็อกเก็ตนั้นจะได้รับผลกระทบ ## L9 โปรเซสเกมฝั่งเซิร์ฟเวอร์ - [ทิกเกินงบเวลา](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-tick-overrun.html): ถ้างานในหนึ่งทิกเกินงบเวลา รอบทิกของเซิร์ฟเวอร์จะยืดออก และทั้งพื้นที่จะช้าลงหรือกระตุก - [การคำนวณระยะมองเห็น (AOI) พุ่ง (N²)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-aoi.html): ถ้าเปรียบเทียบทุกคนกับทุกคนเพื่อหาว่าใครมองเห็นใคร เมื่อจำนวนคนเพิ่มเป็น 10 เท่า การคำนวณจะเพิ่มเป็น 100 เท่า - [ปริมาณ broadcast พุ่ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-broadcast.html): ถ้าส่งการเคลื่อนไหวของผู้เล่นหนึ่งคนไปให้ทุกคนที่มองเห็น จะเกิดอัปเดตที่ต้องส่งเท่ากับจำนวนคนที่รวมตัวยกกำลังสอง - [พื้นที่ที่รันบนเธรดเดียวโหลดเกิน (hotspot)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-hotzone.html): ในโครงสร้างที่แต่ละพื้นที่มีเธรดดูแลตัวเดียว ถ้าคนแห่ไปที่จุดเดียว คอร์ตัวนั้นตัวเดียวจะขึ้นไป 100% - [การแย่งล็อก](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-lock.html): ถ้าหลายเธรดรอล็อกตัวเดียวเพื่อเขียนข้อมูลเดียวกัน ต่อให้เพิ่มเธรด ก็ทำงานได้ทีละตัวเท่านั้น - [เดดล็อก](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-deadlock.html): ถ้าสองเธรดต่างรอล็อกที่อีกฝ่ายถืออยู่ ทั้งคู่จะหยุดไปตลอดกาล - [synchronous call บนเธรดเกม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-sync-call.html): ถ้ารอการตอบกลับจาก DB หรือการเขียนไฟล์กลางทิก การดำเนินเกมทั้งหมดบนเซิร์ฟเวอร์จะหยุดไปเท่ากับเวลานั้น - [ข้อความสะสมในคิว](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-queue.html): ถ้าคำขอเข้ามาเร็วกว่าความเร็วในการประมวลผลจนกองในคิว คำขอที่อยู่ท้ายคิวจะถูกประมวลผลอีกหลายวินาทีต่อมาหรือถูกทิ้ง - [ตัวจับเวลาทำงานพร้อมกันจำนวนมาก](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-timer-burst.html): ถ้าการรีสปอนของมอนสเตอร์ทั้งหมด การหมดอายุของบัฟทั้งหมด และของรางวัลตอนตรงชั่วโมงมารวมในทิกเดียวกัน ทิกนั้นจะหนักขึ้นหลายสิบเท่า - [การคำนวณ pathfinding พุ่ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-pathfinding.html): ถ้ามอนสเตอร์หลายร้อยตัวไล่ตามผู้เล่นและคำนวณเส้นทางพร้อมกัน จะกิน CPU มาก - [ต้นทุนของ serialization และการบีบอัด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-serialize.html): การแปลงข้อมูลที่จะส่งเป็นไบต์และบีบอัดก็ใช้ CPU เช่นกัน และเมื่อคนเยอะ ต้นทุนนี้จะพุ่งสูง - [เซิร์ฟเวอร์แครช](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-crash.html): ถ้าโปรเซสเซิร์ฟเวอร์ตายเพราะข้อผิดพลาดที่ไม่ได้จัดการ ทุกคนในเซิร์ฟเวอร์นั้นจะหลุดพร้อมกัน - [thread pool หมด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-threadpool.html): ถ้า worker thread ที่ประมวลผลงานติดอยู่กับงานช้าทั้งหมด คำขอใหม่จะต้องรอไปเรื่อย ๆ อย่างไม่มีกำหนด - [ลูปไม่รู้จบ/ลอจิกทำงานไม่หยุด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-infinite-loop.html): ถ้าบั๊กทำให้ทิกหนึ่งไม่จบ เซิร์ฟเวอร์จะหยุด และ watchdog จะบังคับรีสตาร์ต - [การต่อสู้ที่รุมเป้าหมายเดียว (เวิลด์บอส)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-hot-entity.html): ถ้าคนหลายร้อยคนตีบอสตัวเดียวพร้อมกัน การคำนวณของบอสตัวนั้นจะกระจุกที่จุดเดียว และข้อมูลการโจมตีจะถูกส่งให้ทุกคนที่มองเห็น - [spawn ทะลักเมื่อเข้าพื้นที่คนหนาแน่น](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-spawn-burst.html): ถ้าเทเลพอร์ตเข้าเมืองที่คนแน่น เซิร์ฟเวอร์ต้องส่งรูปลักษณ์ อุปกรณ์ และสถานะของคนหลายร้อยคนที่เพิ่งมองเห็นไปพร้อมกันรวดเดียว - [เอนทิตีสะสม (ไอเทม/ซัมมอนที่ไม่ถูกเก็บกวาด)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-entity-buildup.html): ถ้าไอเทมที่ตกบนพื้นซึ่งควรหายไปแล้ว ซัมมอน และตัวจับเวลาที่จบแล้วไม่ถูกเก็บกวาดจนกองสะสม ยิ่งเปิดเซิร์ฟเวอร์ไว้นาน งานในแต่ละทิกก็ยิ่งเพิ่ม - [แพตช์ทำให้รูปแบบทราฟฟิกเปลี่ยน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sp-patch-traffic.html): ถ้าคอนเทนต์ เอฟเฟกต์ หรือรายการที่ต้องซิงก์ใหม่ทำให้ขนาดและความถี่ของแพ็กเก็ตเพิ่ม เซิร์ฟเวอร์ที่เคยลื่นจะเริ่มชนขีดจำกัด MTU แบนด์วิดท์ และจำนวนแพ็กเก็ตหลังลงแพตช์ ## L10 หน่วยความจำ - [GC ของเซิร์ฟเวอร์หยุดทั้งระบบ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-gc.html): ระหว่างที่เซิร์ฟเวอร์ Java หรือ C# หยุดทุกเธรดเพื่อเก็บคืน garbage (stop-the-world) ทั้งเซิร์ฟเวอร์จะหยุดชะงักไปด้วย - [GC pause ของสคริปต์เอนจิน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-script-gc.html): แม้เซิร์ฟเวอร์จะเขียนด้วย C++ แต่ถ้ารันเควสต์, AI และสกิลด้วยสคริปต์อย่าง Lua ระหว่างที่ GC ของสคริปต์เอนจินทำงาน โซนนั้นจะหยุดชะงัก - [การจัดสรรหน่วยความจำพุ่ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-alloc.html): ถ้าสร้างออบเจ็กต์ชั่วคราวจำนวนมากระหว่างอีเวนต์ GC จะทำงานบ่อยกว่าปกติมาก - [หน่วยความจำรั่ว](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-leak.html): หน่วยความจำที่ไม่ถูกคืนค่อย ๆ สะสม จนหลายวันต่อมานำไปสู่ GC ทำงานไม่หยุด, สวอป หรือโปรเซสถูกบังคับปิด - [GC thrashing (heap เหลือที่ว่างไม่พอ)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-gc-thrash.html): เมื่อข้อมูลที่ยังใช้อยู่ (live data) เข้าใกล้ขีดจำกัดของ heap แม้ GC ทำงานก็แทบไม่มีอะไรให้เก็บคืน GC จึงวนทำงานซ้ำไม่หยุด - [สวอป](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-swap.html): ถ้าหน่วยความจำไม่พอจน OS ย้ายบางส่วนไปไว้บนดิสก์ ทุกครั้งที่ใช้หน่วยความจำส่วนนั้นต้องรอดิสก์ที่ช้ากว่าเกิน 1,000 เท่า - [แคชมิส](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-cache-miss.html): ถ้าข้อมูลกระจัดกระจายอยู่ทั่วหน่วยความจำ CPU ต้องไปรอถึง RAM ที่ช้าทุกครั้ง - [หน่วยความจำแตกกระจาย (fragmentation)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-fragment.html): ถ้าจัดสรรและคืนหน่วยความจำซ้ำไปมาจนพื้นที่ว่างแตกเป็นชิ้นเล็ก ๆ โปรเซสจะถือครองหน่วยความจำมากกว่าที่ใช้จริงมาก - [หน่วยความจำ NUMA ฝั่งไกล (remote)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/mem-numa.html): บนเซิร์ฟเวอร์ที่มี CPU สองตัว ถ้าใช้หน่วยความจำที่ต่ออยู่กับ CPU อีกฝั่ง การเข้าถึงจะช้าลง ## L11 ดิสก์ - [การเขียน log แบบ synchronous](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-sync-log.html): ถ้าเธรดเกมต้องรอให้ดิสก์เขียนเสร็จทุกครั้งที่เขียน log หนึ่งบรรทัด พอดิสก์ยุ่ง เกมก็หยุดเดินไปด้วย - [fsync ทะลัก](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-fsync.html): ถ้าสั่งให้เขียนข้อมูลลงดิสก์ “แบบแน่นอน” แต่ละครั้งจะใช้เวลา 0.1 ms ถึงหลายสิบ ms แล้วแต่ดิสก์ และถ้ามาพร้อมกันมาก คิวจะยาวขึ้น - [burst credit ของดิสก์คลาวด์หมด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-burst.html): ดิสก์คลาวด์บางประเภทและเซิร์ฟเวอร์สเปกเล็กมี burst credit ที่ให้ทำงานเร็วกว่าประสิทธิภาพพื้นฐานได้ชั่วคราว ถ้าช่วงที่ยุ่งยาวนานจนเครดิตหมด ความเร็วจะตกลงกะทันหัน - [ขีดจำกัด IOPS/คิวดิสก์อิ่มตัว](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-iops.html): ถ้าคำขอเกินจำนวนที่ดิสก์ประมวลผลได้ใน 1 วินาที คิวจะยาวขึ้นและดีเลย์พุ่งสูง - [ดิสก์เต็ม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-full.html): ถ้า log และ dump สะสมจนดิสก์เต็ม การเขียนจะล้มเหลว และถ้าไม่ได้เตรียมรับมือไว้ เซิร์ฟเวอร์จะล่ม - [งานสำรองข้อมูล/บีบอัด/สแกน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-backup.html): ถ้าการสำรองข้อมูลตอนเช้ามืด, การบีบอัด log หรือการสแกนความปลอดภัยยึดดิสก์ไว้ การอ่านและเขียนของเซิร์ฟเวอร์เกมจะล่าช้า - [lazy loading บนเซิร์ฟเวอร์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-lazy-load.html): ถ้าเซิร์ฟเวอร์อ่านข้อมูลดันเจี้ยนหรือแมพจากดิสก์ตอนที่ถูกขอเป็นครั้งแรก ทุกคนจะหยุดไปตลอดทิกนั้น - [การเขียน core dump](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-coredump.html): ตอนเซิร์ฟเวอร์ล่ม ต้องเขียนหน่วยความจำหลาย GB ลงดิสก์ บางครั้งการรีสตาร์ตจึงล่าช้าไปหลายนาที - [ดีเลย์จาก seek ของ HDD](https://jungrok5.github.io/mmo-lag-anatomy/th/c/dk-hdd.html): HDD ต้องเลื่อนหัวอ่านไปบนจานแม่เหล็ก (seek) การอ่านเขียนข้อมูลที่กระจัดกระจายจึงใช้เวลาเกือบ 10 ms ต่อครั้ง ## L12 ฐานข้อมูล - [คิวรีที่ไม่มีอินเด็กซ์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-no-index.html): ถ้าไม่มีอินเด็กซ์ การหาแถวที่ตรงเงื่อนไขต้องอ่านทั้งตาราง (full table scan) - [แย่งล็อกบน hot row](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-hot-row.html): ถ้าทุกคนพยายามแก้แถวเดียวกัน (โกดังกิลด์, ไอเทมฮิตในตลาดประมูล, ตัวนับของทั้งเซิร์ฟเวอร์) จะได้ล็อกทีละคนเท่านั้น - [เดดล็อกใน DB](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-deadlock.html): ถ้าสองทรานแซกชัน (งาน DB ที่ประมวลผลเป็นชุดเดียว) ต่างรอแถวที่อีกฝ่ายล็อกไว้ DB จะบังคับยกเลิกฝั่งหนึ่ง - [connection pool หมด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-pool.html): จำนวนการเชื่อมต่อที่เปิดไว้กับ DB มีจำกัด ถ้าคิวรีที่ช้าถือครองการเชื่อมต่อไว้ คำขอที่เหลือต้องรอ - [การทำสำเนาข้อมูลล่าช้า](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-replica-lag.html): การเขียนไปที่ DB หลัก ส่วนการอ่านทำจาก replica ถ้า replica ตามไม่ทัน ข้อมูลที่เพิ่งเขียนจะยังมองไม่เห็น - [checkpoint/log flush](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-checkpoint.html): จังหวะที่ DB เขียนส่วนที่เปลี่ยนแปลงในหน่วยความจำลงดิสก์รวดเดียวตามรอบ คิวรีจะช้าลง - [cold cache (หลังรีสตาร์ตใหม่ ๆ)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-cold-cache.html): เมื่อรีสตาร์ต DB แคชในหน่วยความจำจะว่างเปล่า ช่วงหนึ่งข้อมูลทุกอย่างที่ดึงจึงต้องอ่านจากดิสก์ - [คนแห่ล็อกอินและคิวรี N+1](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-login-storm.html): ถ้าการโหลดตัวละครหนึ่งตัวต้องดึงข้อมูลแยกกันหลายสิบครั้ง ผู้เล่นหลายหมื่นคนที่ล็อกอินพร้อมกันจะกลายเป็นคิวรีหลายล้านคิวรี - [งาน batch ขนาดใหญ่](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-batch.html): ถ้ารันการสรุปอันดับ, การส่งจดหมายในเกมแบบรวดเดียว หรือการล้างข้อมูลเก่าระหว่างให้บริการ งานเหล่านี้จะยึดล็อกและดิสก์ไว้ - [failover ของ DB](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-failover.html): ระหว่างที่ DB หลักล่มและสลับไปใช้ DB สำรอง จะเขียนข้อมูลไม่ได้ และข้อมูลช่วงท้ายที่ยัง replicate ไม่ทันอาจหายไป - [ความคืบหน้าหายเพราะรอบเซฟยาว](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-save-interval.html): ถ้าเซฟแค่ทุกไม่กี่นาทีเพื่อลดโหลด เมื่อเซิร์ฟเวอร์ล่มในระหว่างนั้น ความคืบหน้าจะหายไป - [แคชสแตมปีด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-cache-stampede.html): ถ้าแคชของข้อมูลยอดนิยมหมดอายุพร้อมกัน คำขอหลายพันรายการจะแห่ไปที่ DB พร้อมกัน - [ทรานแซกชันที่เปิดทิ้งไว้นาน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-long-tx.html): ถ้าทรานแซกชันหนึ่งเปิดทิ้งไว้นาน จะถือล็อกไว้ตลอด และ DB ล้างข้อมูลเวอร์ชันเก่า (purge) ไม่ได้ ทั้งระบบจึงค่อย ๆ ช้าลง - [คำสั่ง Redis ที่ช้า](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-redis-block.html): Redis ประมวลผลคำสั่งทีละคำสั่ง คำสั่งที่ช้าเพียงคำสั่งเดียวจึงขวางทุกคำขอที่ตามมา - [คิวรีช้าเพราะ query plan เปลี่ยน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-plan-flip.html): โค้ดเหมือนเดิม แต่ถ้า DB เปลี่ยนวิธีประมวลผลคิวรีเดิม (query plan) คิวรีที่เมื่อวานใช้ 2 ms วันนี้อาจกลายเป็นหลายร้อย ms - [ล็อกจากการเปลี่ยนสคีมา (DDL) ระหว่างให้บริการ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/db-ddl-lock.html): ถ้าเพิ่มคอลัมน์หรืออินเด็กซ์ให้ตารางระหว่างให้บริการ ล็อกที่ต้องใช้เพียงชั่วครู่ตัวเดียวอาจทำให้ทุกคำขอที่ใช้ตารางนั้นต้องรอ ## L13 สถาปัตยกรรมเซิร์ฟเวอร์และการดูแลระบบ - [การผ่านเกตเวย์/พร็อกซี](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-gateway.html): ถ้าวางเซิร์ฟเวอร์คั่นกลางระหว่างไคลเอนต์กับเซิร์ฟเวอร์เกม ทุกครั้งที่ผ่านจะมีเวลาประมวลผลเพิ่มขึ้น และเซิร์ฟเวอร์ตัวนั้นจะกลายเป็น single point of failure (จุดเดียวที่ล่มแล้วกระทบทั้งระบบ) - [ย้ายโซน (ส่งต่อตัวละครข้ามเซิร์ฟเวอร์)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-zone-transfer.html): เมื่อเข้าพื้นที่หรือดันเจี้ยนอื่น ขั้นตอนส่งข้อมูลตัวละครไปยังเซิร์ฟเวอร์อื่นทำให้เกิดดีเลย์และความล้มเหลว - [ความล้มเหลวแบบลูกโซ่](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-cascade.html): เมื่อเซอร์วิสหนึ่งช้าลง เซิร์ฟเวอร์ที่เรียกใช้เซอร์วิสนั้นจะติดอยู่กับการรอคำตอบ จนฟีเจอร์ที่ไม่เกี่ยวข้องก็หยุดทำงานไปด้วย - [เซิร์ฟเวอร์เสริมขัดข้อง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-subservice.html): ถ้าเซิร์ฟเวอร์ที่รันแยกจากเซิร์ฟเวอร์เกม เช่น แชต, ปาร์ตี้ หรือตลาดประมูล ขัดข้อง จะใช้งานไม่ได้เฉพาะฟีเจอร์นั้น - [การ deploy และรีสตาร์ต](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-deploy.html): ถ้ารีสตาร์ตเซิร์ฟเวอร์เพื่ออัปเดตโดยไม่ย้ายการเชื่อมต่อ ผู้เล่นที่อยู่บนเซิร์ฟเวอร์นั้นจะหลุด และการบันทึกข้อมูลก่อนปิดกับการเชื่อมต่อใหม่จะทะลักเข้ามาพร้อมกัน - [autoscaling เพิ่มเครื่องไม่ทัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-autoscale.html): เมื่อคนแห่เข้ามา ระบบจะเพิ่มเซิร์ฟเวอร์อัตโนมัติ แต่ต้องใช้เวลาเตรียมหลายนาที และระหว่างนั้นเซิร์ฟเวอร์เดิมรับโหลดเกิน - [log และระบบมอนิเตอร์โหลดเกิน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-monitoring.html): เมื่อเกิดเหตุขัดข้อง log จะพุ่งขึ้นมาก และเซิร์ฟเวอร์ที่ส่ง log แบบ synchronous จะยิ่งช้าลงเพราะ log - [นาฬิการะหว่างเซิร์ฟเวอร์ไม่ตรงกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-clock-skew.html): ถ้านาฬิกาของแต่ละเซิร์ฟเวอร์ต่างกันเล็กน้อย การตัดสินคูลดาวน์, บัฟ และเวลาเริ่มอีเวนต์จะไม่ตรงกันระหว่างเซิร์ฟเวอร์ - [มาโครและบอทมากเกินไป](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-bots.html): บอทส่งคำขอถี่กว่าคนมาก จึงกินกำลังประมวลผลของเซิร์ฟเวอร์ - [การพึ่งพาเซอร์วิสภายนอก](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-external.html): ถ้าเซอร์วิสภายนอก เช่น ล็อกอินผ่านแพลตฟอร์ม, การชำระเงิน หรือการยืนยันตัวตน ช้าหรือหยุดทำงาน ผู้เล่นจะติดอยู่ที่ขั้นตอนนั้น - [matchmaking/การจัดรีเจียนผิดพลาด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-region-match.html): ถ้าถูกจัดไปเซิร์ฟเวอร์ในรีเจียนที่ไกลแทนรีเจียนที่ใกล้ ผู้เล่นคนนั้นจะปิงสูงตลอดแม้เน็ตจะปกติ - [ใบรับรอง TLS หมดอายุ/ตั้งค่าผิด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-cert.html): ถ้าใบรับรองของเซิร์ฟเวอร์ล็อกอิน, API หรือแพตช์หมดอายุ หรือขาดใบรับรองกลาง (intermediate certificate) ไคลเอนต์ที่เชื่อมต่อใหม่ตั้งแต่วินาทีนั้นจะเชื่อมต่อ TLS ไม่สำเร็จ - [คิวล็อกอินชนเพดานและ grace period ตอนเชื่อมต่อใหม่ไม่พอ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/in-login-queue.html): เมื่อคนแห่เข้ามาทันทีหลังเปิดตัวเกมหรือปิดปรับปรุง คิวล็อกอินจะชนเพดานจนปฏิเสธคนที่จะเข้าคิวใหม่ และผู้เล่นที่รออยู่ถ้าหลุดไปแป๊บเดียวก็เสียลำดับคิวแล้วต้องกลับไปต่อท้าย ## การออกแบบการซิงก์ - [แสดงผลหลังเซิร์ฟเวอร์ตอบเท่านั้น (แบบ request-response)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-request-response.html): กดปุ่มแล้วไม่มีทั้งแอนิเมชันและเสียงจนกว่าคำตอบจากเซิร์ฟเวอร์จะมาถึง ปิงจึงกลายเป็นความเร็วในการตอบสนองโดยตรง - [โปรโตคอลที่ต้องไปกลับตามลำดับหลายรอบ (chatty)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-chatty.html): ถ้าการกระทำหนึ่งครั้งต้องไปกลับเซิร์ฟเวอร์หลายรอบตามลำดับ ปิงจะคูณตามจำนวนรอบนั้น - [ไม่มีการกดสกิลล่วงหน้า](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-no-queue.html): ถ้าต้องได้การยืนยันจากเซิร์ฟเวอร์ว่าสกิลก่อนหน้าจบแล้วจึงจะกดสกิลถัดไปได้ ทุกคอมโบจะมีเวลาไปกลับแทรกเข้ามา - [ช่วงเวลาตัดสินสั้นจนปิงกินหมด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-short-window.html): ถ้าเวลาที่ต้องตอบสนอง เช่น การหลบ, การแพร์รี และการกัน สั้นเกินไป ปิงจะกินเวลานั้นไปจนเกิดการโจมตีที่หลบไม่ได้ - [การตัดสินผลที่ไม่มี lag compensation](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-no-lagcomp.html): ถ้าเซิร์ฟเวอร์ตัดสินการโดนโดยดูแค่ “ตำแหน่งบนเซิร์ฟเวอร์ ณ ตอนนี้” ผลการตัดสินจะไม่ตรงกับที่เราเห็นบนจอ - [lag compensation มากเกินไป](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-lagcomp-overreach.html): ถ้าย้อนเวลาให้ผู้โจมตีไกลเกินไป ฝ่ายที่ถูกโจมตีจะโดนทั้งที่หลบไปแล้ว - [client authoritative](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-client-auth.html): ถ้าแต่ละคนตัดสินผลของตัวเอง จอของเราจะลื่น แต่ผลจะไม่ตรงกับจอของคนอื่นและโกงได้ง่าย - [lockstep ต้องรอผู้เล่นที่ช้าที่สุด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-lockstep.html): ในโครงสร้างที่ทุกคนคำนวณเทิร์นเดียวกันไปพร้อมกัน ถ้าอินพุตของคนหนึ่งช้า ทุกคนต้องรอ - [rollback netcode คาดการณ์พลาด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-rollback.html): แสดงผลไปก่อนโดยคาดการณ์อินพุตของอีกฝ่าย ถ้าผิดจะย้อนกลับไปคำนวณใหม่ ยิ่งปิงสูง ช่วงที่ต้องย้อนยิ่งยาว - [เล่นทันทีที่มาถึงโดยไม่มี timestamp](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-no-timestamp.html): ถ้าไม่ติดเวลาที่เกิดให้อีเวนต์จากเซิร์ฟเวอร์ แล้วเล่นทันทีที่ได้รับ จังหวะการแสดงผลจะไม่สม่ำเสมอตามจิตเตอร์ของเครือข่าย - [รอทิกซ้อนสองชั้น](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-double-tick.html): ถ้าเก็บคำขอรอจนถึงทิกถัดไปแล้วจึงประมวลผล และส่งผลลัพธ์ในทิกถัดจากนั้นอีก ช่วงห่างระหว่างทิกจะถูกบวกเพิ่มสองครั้ง - [เซิร์ฟเวอร์ตรวจสอบเข้มงวดเกินไป](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-strict-check.html): ถ้าเซิร์ฟเวอร์ตรวจความเร็วการเคลื่อนที่, คูลดาวน์ และระยะเข้มงวดเกินไป จะปฏิเสธแม้อินพุตปกติที่มาถึงรวมกันเพราะจิตเตอร์ - [โครงสร้างแบบโฮสต์ (หัวห้อง)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-host.html): ถ้า PC ของผู้เล่นคนหนึ่งทำหน้าที่เป็นเซิร์ฟเวอร์ เน็ตและสเปก PC ของคนนั้นจะกำหนดฟีลการเล่นของทุกคน - [แสดงผลล่วงหน้าแล้วเซิร์ฟเวอร์ปฏิเสธ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-optimistic-reject.html): ถ้าการโจมตีหรือสกิลที่จอเราแสดงไปก่อนแล้วถูกเซิร์ฟเวอร์ปฏิเสธทีหลัง ผลที่เห็นกับตาจะกลายเป็นเหมือนไม่เคยเกิดขึ้น - [การคำนวณเส้นทางไม่ตรงกันในการซิงก์คำสั่ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-path-mismatch.html): ถ้ารับส่งแค่ “ให้ไปที่นี่” แล้วแต่ละฝั่งคำนวณเส้นทางเอง เมื่อการคำนวณต่างกันแม้เพียงเล็กน้อย ตัวละครหรือมอนสเตอร์จะเดินไปคนละเส้นทางแล้วถูกดึงกลับมาที่ตำแหน่งที่ถูกต้อง - [อัตราส่งสแนปช็อตต่ำ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/sy-low-send-rate.html): ถ้าเซิร์ฟเวอร์ส่งอัปเดตตำแหน่ง (สแนปช็อต) แค่ไม่กี่ครั้งใน 1 วินาที ต้องตั้ง interpolation buffer ให้ยาวตามไปด้วย จึงเห็นตัวละครอื่นเป็นภาพในอดีตที่ไกลขึ้น ## ปัญหาที่เกิดกับบางคนเท่านั้น - [คนเน็ตช้าขยับแบบกรอเร็วบนจอคนอื่น](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-slow-burst.html): อินพุตของคนที่เน็ตไม่ดีจะไปถึงเซิร์ฟเวอร์แบบไม่สม่ำเสมอและมาเป็นกลุ่ม ถ้าเซิร์ฟเวอร์ใช้คำสั่งตามที่ได้รับในแต่ละทิก คนอื่นจะเห็นตัวละครนั้นหยุดแวบแล้วเดินหลายก้าวในทีเดียว - [อาการกรอเร็วจากเซิร์ฟเวอร์ที่ประมวลผลทันทีที่ได้รับ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-event-server.html): บนเซิร์ฟเวอร์ที่ประมวลผลและแจ้งผลทันทีที่แพ็กเก็ตมาถึง การกระทำของคนที่ช้าซึ่งมาถึงเป็นกลุ่มจะถูกรันทันทีต่อเนื่องกัน - [ขนาดบัฟเฟอร์อินพุตของผู้เล่นแต่ละคน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-input-buffer.html): ถ้าเซิร์ฟเวอร์เก็บอินพุตของแต่ละคนไว้เล็กน้อยแล้วดึงมาใช้ทิกละหนึ่งอัน คนอื่นจะเห็นลื่นไหล แต่จังหวะที่การกระทำของเจ้าตัวถูกยืนยันบนเซิร์ฟเวอร์จะช้าลงตามไปด้วย - [false positive ของการตรวจสอบที่กระจุกกับผู้ใช้บาง ISP](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-isp-validation.html): คนที่ใช้เน็ตที่จิตเตอร์สูง อินพุตจะไปถึงเป็นกลุ่ม จึงติดการตรวจความเร็วและคูลดาวน์ของเซิร์ฟเวอร์บ่อย - [เพื่อนในปาร์ตี้ที่ช้าหนึ่งคนกับกิมมิกบอส](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-raid-member.html): ในกิมมิกเรดที่ทุกคนต้องตอบสนองพร้อมกันในจังหวะที่กำหนด การตอบสนองช้าของคนที่ช้าเพียงคนเดียวจะทำให้ทั้งปาร์ตี้ล้มเหลว - [สิทธิ์ควบคุมมอนสเตอร์อยู่ที่ไคลเอนต์ที่ช้า](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-mob-control.html): บางเกมให้ไคลเอนต์ของผู้เล่นคนหนึ่งที่อยู่ใกล้คำนวณการเคลื่อนที่ของมอนสเตอร์เพื่อลดโหลดเซิร์ฟเวอร์ ถ้าเน็ตของคนนั้นไม่ดี มอนสเตอร์ตัวนั้นจะขยับแปลก ๆ บนจอของทุกคน - [ข้อมูลของตัวละครบางตัวใหญ่เกินไป](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-heavy-char.html): ตัวละครที่มีไอเทมหรือจดหมายสะสมหลายพันชิ้น หรือมีรายชื่อเพื่อน รายชื่อบล็อก และบัฟมากผิดปกติ ต้องโหลดตอนเชื่อมต่อ บันทึก และแจ้งคนรอบข้างมากกว่าคนอื่นหลายเท่า จึงช้าเฉพาะตัวละครนั้นโดยไม่เกี่ยวกับเน็ต - [แชนแนล/อินสแตนซ์/phasing ต่างกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-phase.html): ถ้าตัวละครสองตัวอยู่คนละแชนแนลหรือคนละอินสแตนซ์ หรืออยู่คนละ “phase” ที่เห็น NPC ต่างกันตามความคืบหน้าของเควสต์ จะเห็นโลกคนละแบบ - [ทิ้งข้อความแจ้งการปรากฏตัวที่มาถึงระหว่างโหลด](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-loading-drop.html): ทันทีที่เข้าโซน เซิร์ฟเวอร์ส่งข้อความแจ้งการปรากฏตัวของ NPC รอบตัวมา แต่ไคลเอนต์ยังโหลดแมพอยู่จึงทิ้งข้อความนั้น - [ลำดับการลงทะเบียนระยะมองเห็นพันกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-aoi-race.html): ถ้าจังหวะที่ตัวละครถูกลงทะเบียนในตาราง (grid) ระยะมองเห็นตรงกับจังหวะที่ NPC ย้ายช่องตาราง ข้อความแจ้งการปรากฏตัวของ NPC นั้นอาจตกหล่น - [สแนปช็อตตั้งต้น (baseline) หาย](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-baseline.html): ในแบบที่เซิร์ฟเวอร์ส่ง “เฉพาะส่วนที่ต่างจากครั้งก่อน” ถ้าข้อมูลเต็ม (baseline) ที่ส่งครั้งแรกหายไป ก็จะใช้ส่วนเปลี่ยนแปลงที่ตามมาไม่ได้ - [ข้อความแจ้งการออกไปหาย (ตัวผี)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-ghost.html): ในทางกลับกัน ถ้าพลาดข้อความแจ้งว่า “หายไปแล้ว” NPC หรือผู้เล่นที่ตายหรือออกไปแล้วจะยังอยู่บนจอเราคนเดียว - [ข้อมูลการปรากฏตัวที่ทะลักมาหลังเข้าโซนหาย](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-spawn-burst.html): วินาทีที่เข้าโซน เซิร์ฟเวอร์จะส่งข้อมูลการปรากฏตัวของเอนทิตีรอบตัวหลายสิบถึงหลายร้อยตัวมาพร้อมกัน ถ้าส่งผ่านช่องทางแบบ unreliable หรือ receive buffer ล้นในช่วงที่ยังโหลดอยู่จนอ่านซ็อกเก็ตไม่ได้ บางส่วนจะหายไปและไม่ถูกส่งมาอีก - [สับสนจากการนำ entity ID กลับมาใช้ซ้ำ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-id-reuse.html): ถ้าเซิร์ฟเวอร์ใช้ entity ID เดิมซ้ำเมื่อ NPC ที่ตายเกิดใหม่ ไคลเอนต์ที่พลาดข้อความแจ้งการออกไปในช่วงนั้นจะเข้าใจผิดว่า NPC ตัวใหม่คือตัวเก่า - [พอร์ต UDP แบบตายตัวชนกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-port-collision.html): ถ้าไคลเอนต์ถูกออกแบบให้ใช้พอร์ตภายในเครื่องที่กำหนดตายตัว ไคลเอนต์ตัวที่สองบน PC เดียวกันจะใช้พอร์ตไม่ได้ หรือต้องแบ่งรับแพ็กเก็ตกับตัวแรก - [บั๊กแยกเซสชันด้วย IP/ID เครื่อง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-session-key.html): ถ้าเซิร์ฟเวอร์หรือเซิร์ฟเวอร์ตัวกลางแยกการเชื่อมต่อด้วย IP หรือ ID เครื่อง สองไคลเอนต์ใน PC เดียวกัน (public IP เดียวกัน) จะถูกมองเป็นคนเดียว - [การจำกัดการเปิดหลายไคลเอนต์](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-multiclient.html): ถ้าโมดูลความปลอดภัยหรือนโยบายของเซิร์ฟเวอร์จำกัดการเปิดหลายไคลเอนต์ใน PC เดียว ไคลเอนต์ตัวที่สองจะเปิดหรือเชื่อมต่อไม่ได้ หรือตัวที่เปิดก่อนจะหลุด บางเกมบล็อกแค่บางฟีเจอร์ของไคลเอนต์ที่เปิดเพิ่ม - [จำกัดการประมวลผลของหน้าต่างเบื้องหลัง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-background.html): สำหรับไคลเอนต์ที่เป็นหน้าต่างเบื้องหลัง ตัวเกม เอนจิน และ OS จะลดเฟรมและการประมวลผลลง แพ็กเก็ตที่ได้รับจึงประมวลผลไม่ทันจนกองรอหรือล้น - [การเข้าถึงไฟล์แคช/แอสเซ็ตพร้อมกันจนชนกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-asset-lock.html): ถ้าสองไคลเอนต์เขียนลงโฟลเดอร์แคชเดียวกันพร้อมกันหรือล็อกไฟล์ไว้ ฝั่งหนึ่งจะโหลดโมเดลหรือเท็กซ์เจอร์ของ NPC ไม่ได้ - [หน่วยความจำ/VRAM ไม่พอจนสตรีมล้มเหลว](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-vram.html): ถ้าสองไคลเอนต์แบ่งหน่วยความจำกราฟิกกันใช้ จะไม่มีที่ให้โหลดโมเดลหรือเท็กซ์เจอร์ที่ต้องใช้ใหม่ บางส่วนจึงไม่ถูกวาด - [ตัวเลือกการแสดงผลต่างกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-display-option.html): ถ้าตัวเลือกอย่างการจำกัดจำนวนตัวละครที่แสดง, การซ่อนป้ายชื่อหรือโมเดล NPC และโหมดสเปกต่ำ ตั้งไว้ต่างกันในสองไคลเอนต์ สิ่งที่มองเห็นก็จะต่างกัน - [เวอร์ชันไคลเอนต์/ข้อมูลไม่ตรงกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-version.html): ถ้าไคลเอนต์ตัวที่สองเป็นตัวติดตั้งอื่นหรือแพตช์ยังไม่ครบ จะไม่รู้จัก NPC ID ใหม่ที่เซิร์ฟเวอร์ส่งมา และข้ามไปเงียบ ๆ - [งบการส่ง/ลำดับความสำคัญต่อการเชื่อมต่อ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-priority.html): ถ้าเซิร์ฟเวอร์จำกัดปริมาณที่ส่งต่อการเชื่อมต่อและส่งสิ่งที่อยู่ใกล้ก่อน ฝั่งที่ถูกตั้งเพดานไว้ต่ำจะได้รับ NPC ที่อยู่ไกลช้าหรือไม่ได้รับเลย - [เอนทิตีถูกพักไว้เพราะประมาณเวลาคลาดเคลื่อน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/pt-clock-hold.html): ถ้าเวลาเซิร์ฟเวอร์ที่ไคลเอนต์ประมาณไว้ผิด ข้อมูลเอนทิตีที่เพิ่งมาถึงจะถูกพักไว้เพราะ “ยังเป็นอนาคต” หรือถูกทิ้งเพราะ “เก่าเกินไป” ## ต้นเหตุของการส่งซ้ำใน TCP - [แพ็กเก็ตหายช่วงไร้สาย](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-wireless.html): Wi-Fi และเครือข่ายมือถือจะลองส่งซ้ำในช่วงไร้สายอยู่หลายครั้ง ถ้ายังไม่สำเร็จก็จะทิ้งแพ็กเก็ตนั้น แล้ว TCP จะส่งแพ็กเก็ตที่ถูกทิ้งใหม่หลังจากนั้นพักใหญ่ - [คิวคอขวดล้น (แพ็กเก็ตหายจากความแออัด)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-queue-drop.html): จุดที่แคบที่สุดบนเส้นทาง เช่น เราเตอร์, ลิงก์เชื่อมระหว่าง ISP หรือลิงก์ของดาต้าเซ็นเตอร์ เมื่อคิวตรงนั้นเต็ม แพ็กเก็ตที่มาใหม่จะถูกทิ้ง - [บัฟเฟอร์ตื้นล้นเพราะ burst จากฝั่งส่ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-burst.html): ถ้าเซิร์ฟเวอร์ส่งอัปเดตของผู้เล่นหลายพันคนออกไปรวดเดียวในทุกทิก บัฟเฟอร์เล็ก ๆ ของสวิตช์หรือขีดจำกัดชั่วขณะของคลาวด์จะล้นภายในไม่ถึง 1 ms และแพ็กเก็ตบางส่วนถูกทิ้ง - [policer ทิ้งส่วนที่เกิน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-policer.html): แพ็กเกจเน็ตของ ISP, ขีดจำกัดของอินสแตนซ์คลาวด์ และอุปกรณ์ป้องกัน DDoS บางครั้งจะทิ้งแพ็กเก็ตที่เกินความเร็วที่กำหนดทันทีโดยไม่เข้าคิว - [ข้อผิดพลาดทางกายภาพ (สายเสีย/โมดูลออปติก/คอนเน็กเตอร์)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-physical.html): สายที่ชำรุด, คอนเน็กเตอร์ไฟเบอร์ที่มีฝุ่น และโมดูลออปติกที่หมดอายุการใช้งาน ทำให้เกิด bit error และอุปกรณ์จะทิ้งแพ็กเก็ตที่เสียไปเงียบ ๆ - [duplex ไม่ตรงกัน](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-duplex.html): ถ้าฝั่งหนึ่งใช้ auto-negotiation แต่อีกฝั่งล็อกความเร็วและ duplex ไว้ ฝั่งหนึ่งจะทำงานแบบ half duplex และทุกครั้งที่มีโหลดจะเกิด collision จนแพ็กเก็ตหาย - [เครื่องเซิร์ฟเวอร์ฝั่งรับทิ้งแพ็กเก็ต](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-host-drop.html): แพ็กเก็ตมาถึงเซิร์ฟเวอร์แล้ว แต่ถูกทิ้งเพราะ ring buffer ของ NIC (บัฟเฟอร์ที่พักแพ็กเก็ตที่มาถึงไว้ชั่วคราว) ล้น หรือคอร์ที่เคอร์เนลใช้ประมวลผลขาเข้าทำงานเต็ม - [ไฟร์วอลล์/connection tracking ทิ้งแพ็กเก็ต](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-stateful-fw.html): ไฟร์วอลล์หรือ connection tracking ของ Linux (conntrack คือฟังก์ชันที่บันทึกการเชื่อมต่อที่ผ่านลงในตาราง) จะทิ้งแพ็กเก็ตเมื่อตารางเต็ม หรือเมื่อตัดสินว่าสถานะการเชื่อมต่อไม่ถูกต้อง - [อุปกรณ์กลางทางเกินขีดความสามารถ (ไฟร์วอลล์/IPS/ระบบป้องกัน DDoS)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-appliance-pps.html): ไฟร์วอลล์, อุปกรณ์ป้องกันการบุกรุก (IPS) และอุปกรณ์ป้องกัน DDoS ตรวจแพ็กเก็ตที่ผ่านทีละตัว เมื่อเกินความสามารถในการตรวจ แพ็กเก็ตที่ประมวลผลไม่ทันจะถูกทิ้งตั้งแต่จังหวะนั้น - [MTU black hole (เฉพาะแพ็กเก็ตใหญ่ที่หายซ้ำแล้วซ้ำอีก)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-mtu.html): เมื่อขนาดที่ช่วงกลางทางรับได้เล็กลง แต่ข้อความแจ้งว่า “ใหญ่เกินไป” (ICMP) ถูกบล็อก แพ็กเก็ตใหญ่จะหายไปทุกครั้งไม่ว่าจะส่งซ้ำกี่รอบ - [mapping ของ NAT/โหลดบาลานเซอร์หมดอายุกลางการเชื่อมต่อ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-mapping.html): ถ้าอุปกรณ์กลางทางลบ mapping (รายการที่บันทึกว่าจะส่งต่อการเชื่อมต่อนี้ไปที่ไหน) ของการเชื่อมต่อที่ idle แพ็กเก็ตถัดไปที่ส่งจะไปไม่ถึง การเชื่อมต่อจะส่งซ้ำวนไปจนหลุด หรืออุปกรณ์ตอบกลับด้วยการปฏิเสธการเชื่อมต่อ (RST) แล้วหลุดทันที - [เส้นทางเปลี่ยน/เส้นทาง ECMP ที่เสีย](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-path.html): แพ็กเก็ตจะหายไปในช่วงไม่กี่วินาทีที่เส้นทางอินเทอร์เน็ตเปลี่ยน หรือในการเชื่อมต่อที่ถูกจัดให้วิ่งบนเส้นทางที่เสียจากหลายเส้นทาง ECMP - [การส่งซ้ำโดยไม่จำเป็นเพราะความหน่วงพุ่ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-spurious-delay.html): แพ็กเก็ตยังอยู่ครบและแค่มาถึงช้ามากชั่วครู่ แต่ถ้าความหน่วงนั้นนานกว่า RTO ฝั่งส่งจะตัดสินว่าหายแล้วส่งซ้ำ - [fast retransmit โดยไม่จำเป็นเพราะแพ็กเก็ตสลับลำดับ](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-reorder.html): เมื่อแพ็กเก็ตสลับลำดับเพราะวิ่งผ่านหลายเส้นทางหรือลิงก์ที่รวมกัน ฝั่งรับจะแจ้งว่า “มีแพ็กเก็ตขาดหาย” ด้วย duplicate ACK และฝั่งส่งจะส่งแพ็กเก็ตที่ไม่ได้หายซ้ำ - [ACK มาช้าหรือหาย (อัปโหลดเต็ม)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-ack-path.html): ข้อมูลมาถึงเรียบร้อย แต่ถ้า ACK ที่บอกว่า “ได้รับแล้ว” ไปติดอยู่ในคิวอัปโหลดที่เต็มจนช้าหรือหาย ฝั่งส่งจะตัดสินว่าหายแล้วส่งซ้ำ - [ค่า RTO ไม่เหมาะกับสภาพแวดล้อม](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-rto-setting.html): ถ้าลดค่าต่ำสุดของ RTO มากเกินไป แค่ช้านิดเดียวก็เกิดการส่งซ้ำโดยไม่จำเป็น ส่วนค่าเริ่มต้น (200 ms) ก็นานเกินไปสำหรับเกม ทุกครั้งที่แพ็กเก็ตหายจึงหยุดนาน - [thin stream กู้คืนช้า](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-thin.html): ถ้าส่งแพ็กเก็ตเล็ก ๆ ห่าง ๆ แบบเกม RTO จะมาถึงก่อนที่ “แพ็กเก็ตที่ตามมา 3 ตัว” จะครบ เมื่อหายเท่ากัน จึงหยุดนานกว่าการส่งข้อมูลปริมาณมากอยู่มาก - [อุปกรณ์กลางทางตัด TCP option ทิ้ง](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-sack-stripped.html): ถ้าไฟร์วอลล์หรืออุปกรณ์เร่งความเร็วบางตัวลบหรือแก้ TCP option เมื่อแพ็กเก็ตหายหลายตัว จะกู้คืนได้แค่ตัวเดียวต่อหนึ่งรอบไปกลับ หรือ window (ปริมาณที่ส่งได้ในครั้งเดียว) จะเล็กลงจนช้า - [zero window (การหยุดที่ดูเหมือนการส่งซ้ำ)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-zero-window.html): ถ้าโปรแกรมฝั่งรับอ่านซ็อกเก็ตไม่ทันจนบัฟเฟอร์เต็ม ฝั่งส่งจะหยุดส่งและส่งแค่ zero window probe ปัญหานี้ไม่ได้อยู่ที่เน็ต - [การส่งซ้ำคำขอเชื่อมต่อ (SYN)](https://jungrok5.github.io/mmo-lag-anatomy/th/c/rt-syn.html): ถ้าคำขอเชื่อมต่อหายไปเพราะคิวรอเชื่อมต่อ (backlog) ล้นหรือถูกไฟร์วอลล์บล็อก OS ฝั่งไคลเอนต์จะส่งใหม่ โดยเริ่มหลัง 1 วินาทีและเว้นช่วงห่างขึ้นเรื่อย ๆ ## การชี้สาเหตุและกรณีศึกษา - [ชี้สาเหตุจากข้อมูลที่วัดได้](https://jungrok5.github.io/mmo-lag-anatomy/th/#judge): ลำดับการชี้สาเหตุ ขอบเขต → ช่วงเวลา → ชั้น, ตารางสัญญาณ, รูปแบบกราฟ 13 แบบ, วิธีอ่านตัวเลข (ค่าเฉลี่ยกับ p99) - [ขั้นตอนตามสถานการณ์](https://jungrok5.github.io/mmo-lag-anatomy/th/text.html#playbooks): แลคหลังลงแพตช์, การขยายบริการไปประเทศหรือภูมิภาคใหม่ - [กรณีเหตุขัดข้องจริง](https://jungrok5.github.io/mmo-lag-anatomy/th/text.html#cases): รายงาน postmortem ที่ผู้พัฒนาต้นทางและผู้ให้บริการเกมเผยแพร่ พร้อมสาเหตุที่เกี่ยวข้อง ## ภาษาอื่น - [한국어 (Korean)](https://jungrok5.github.io/mmo-lag-anatomy/llms.txt) - [English](https://jungrok5.github.io/mmo-lag-anatomy/en/llms.txt) - [日本語 (Japanese)](https://jungrok5.github.io/mmo-lag-anatomy/ja/llms.txt) - [简体中文 (Chinese (Simplified))](https://jungrok5.github.io/mmo-lag-anatomy/zh-cn/llms.txt) - [繁體中文 (Chinese (Traditional, Taiwan))](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/llms.txt) - [Deutsch (German)](https://jungrok5.github.io/mmo-lag-anatomy/de/llms.txt) - [Tiếng Việt (Vietnamese)](https://jungrok5.github.io/mmo-lag-anatomy/vi/llms.txt) - [Русский (Russian)](https://jungrok5.github.io/mmo-lag-anatomy/ru/llms.txt) - [Português (Brasil) (Portuguese (Brazil))](https://jungrok5.github.io/mmo-lag-anatomy/pt-br/llms.txt) - [Español (Spanish)](https://jungrok5.github.io/mmo-lag-anatomy/es/llms.txt) - [Bahasa Indonesia (Indonesian)](https://jungrok5.github.io/mmo-lag-anatomy/id/llms.txt) ## Optional - [รีโพซิทอรีบน GitHub](https://github.com/jungrok5/mmo-lag-anatomy): ซอร์สโค้ด, รูปแบบข้อมูล, วิธีร่วมพัฒนา - [ผู้จัดทำ: Jeongrok Oh](https://jungrok5.github.io/resume/en/): เรซูเม่