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

คู่มือเกมแลค › 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 ของไฟล์โปรแกรมออกจากหน่วยความจำแล้วอ่านกลับซ้ำ ๆ ทั้งเซิร์ฟเวอร์จึงอาจช้าลงอย่างหนักไปพักหนึ่งก่อนถูกบังคับปิด

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

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

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

ชั้นเดียวกัน: L10 หน่วยความจำ

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

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