คู่มือเกมแลค › L10 หน่วยความจำ
สวอป Swapping
ID สาเหตุ mem-swap · ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →
ถ้าหน่วยความจำไม่พอจน OS ย้ายบางส่วนไปไว้บนดิสก์ ทุกครั้งที่ใช้หน่วยความจำส่วนนั้นต้องรอดิสก์ที่ช้ากว่าเกิน 1,000 เท่า
ทำไม หน่วยความจำที่ใช้เกิน RAM จริง → ผลคือ OS ย้ายบางส่วนไปไว้บนดิสก์และอ่านกลับเมื่อต้องใช้ → บนหน้าจอ เวลาต่อทิกพุ่งเป็นหลายร้อย ms ผู้เล่นทุกคนบนเซิร์ฟเวอร์เจอสโลว์โมชั่นและค้าง
- อาการ
- สโลว์โมชั่น, ค้าง
- ปัจจัย
- การหยุดชะงัก
- ใครเจอ
- ทั้งเซิร์ฟเวอร์
- เกิดเมื่อไร
- ยิ่งเปิดไว้นานยิ่งเป็น, ช่วงพีคหัวค่ำ
- ผู้รับผิดชอบ
- ผู้รับผิดชอบหลัก อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา) · ร่วมกับ พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม)
- งานฝั่งทีมพัฒนาเกม
- กำหนดเพดานการใช้หน่วยความจำของโปรเซส (เช่น ขนาด heap) และตรวจหาการรั่ว
- งานฝั่งทีมอินฟรา
- ตั้งไม่ให้เซิร์ฟเวอร์เกมใช้สวอป, รับมือด้วย alert หน่วยความจำ, ถ้าปิดสวอป โปรเซสจะถูกบังคับปิด (OOM) ทันทีที่หน่วยความจำไม่พอ จึงต้องมี RAM เหลือมากกว่าการใช้งานตอนพีคอย่างเหลือเฟือ
- ตัวเลขที่ควรรู้
- อ่าน RAM ประมาณ 100 ns, อ่านกลับจาก SSD ประมาณ 100 µs (1,000 เท่า), ดิสก์คลาวด์ที่อยู่อีกฝั่งของเครือข่ายประมาณ 1 ms (1 หมื่นเท่า), HDD 10 ms (1 แสนเท่า)
- บนกราฟ
- ค่อย ๆ สูงขึ้น · ปริมาณการใช้สวอป, swap in/out
- จุดที่ต้องดู
- คอลัมน์ si และ so ของ vmstat 1 (ปริมาณที่อ่านเข้าจากสวอปและเขียนออกไปสวอปต่อวินาที), some และ full ใน /proc/pressure/memory (สัดส่วนเวลาที่หยุดรอหน่วยความจำ) และ majflt/s จาก pidstat -r ของโปรเซสเซิร์ฟเวอร์เกม (page fault ที่ต้องอ่านจากดิสก์) วางซ้อนกับเวลาต่อทิก
- สัญญาณว่าใช่
- ช่วงที่แลค si มากกว่า 0 และ majflt/s ของเซิร์ฟเวอร์เกมกับค่า full ของ memory สูงขึ้นพร้อมกัน
- สัญญาณว่าไม่ใช่
- si และ so เป็น 0 และแรงกดดันของ memory (PSI) ก็ใกล้ 0: สวอปไม่ใช่สาเหตุ ถ้าไม่มีสวอปแต่ majflt/s และ PSI สูงขึ้น แปลว่าหน่วยความจำหมดจนต้องอ่าน code page ซ้ำ ต้องหาหน่วยความจำเพิ่มก่อน
- วิธีตรวจ
- ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
- รายละเอียดเพิ่มเติม
- เซิร์ฟเวอร์ที่ใช้ GC ต้องอ่าน heap ทั่วทุกส่วนตอนเก็บคืน แม้ heap ถูกสวอปออกไปแค่บางส่วน GC หนึ่งครั้งก็อาจยืดเป็นหลายวินาทีถึงหลายสิบวินาที ถ้าปิดสวอป โปรเซสจะข้ามช่วงที่ช้าลงเพราะสวอปไปถูกบังคับปิด (OOM) ทันที จึงต้องกันหน่วยความจำเหลือไว้ก่อน แม้ไม่มีสวอป ถ้าหน่วยความจำใกล้หมด OS จะเอาแม้แต่ code page ของไฟล์โปรแกรมออกจากหน่วยความจำแล้วอ่านกลับซ้ำ ๆ ทั้งเซิร์ฟเวอร์จึงอาจช้าลงอย่างหนักไปพักหนึ่งก่อนถูกบังคับปิด
แหล่งอ้างอิง
- Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote) Google
“Numbers Everyone Should Know”: อ้างอิงหน่วยความจำหลัก 100 ns, seek ดิสก์ 10 ms (ข้อมูลปี 2009) - Documentation for /proc/sys/vm/ Linux kernel
swappiness: ต้นทุนเทียบกันระหว่างการสวอปกับการเก็บคืน file page, สวอปเป็น random I/O จึงแพง - Concepts overview Linux kernel
เก็บคืน page cache ที่มีต้นฉบับอยู่บนดิสก์และ page ที่สวอปได้ ถ้ายังไม่พอ OOM killer จะฆ่าโปรเซส - Solidigm™ D7-P5520 and D7-P5620 Product Brief Solidigm
ความหน่วงที่ 99.99% (four-nines latency) ของ NVMe SSD สำหรับเซิร์ฟเวอร์คือ 130 µs: เป็นหลักฐานว่าการอ่าน SSD หนึ่งครั้งใช้ราว 100 µs - Amazon EBS General Purpose SSD volumes AWS
ความหน่วงของดิสก์คลาวด์พื้นฐาน (gp3) อยู่ในระดับหลักหน่วย ms - vmstat(8) — Linux manual page procps-ng
si: หน่วยความจำที่อ่านเข้าจากสวอปต่อวินาที, so: หน่วยความจำที่เขียนออกไปสวอปต่อวินาที - PSI - Pressure Stall Information Linux kernel
some (สัดส่วนเวลาที่งานบางส่วนหยุด) และ full (สัดส่วนเวลาที่งานทั้งหมดหยุดพร้อมกัน) ใน /proc/pressure/memory - pidstat(1) — Linux manual page sysstat
-r: majflt/s (จำนวน fault ที่ต้องอ่าน page จากดิสก์)
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: L10 หน่วยความจำ
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (สโลว์โมชั่น)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง