แน่นอนครับว่าการจัดการหน่วยความจำใน Linux เป็นเรื่องยากที่จะเข้าใจครับ
ออกแบบระบบยังไง? ให้แอพพลิเคชั่นกินแรม แล้วต่อด้วยกิน swap 555+++ ก็แค่ Firefox processes รัน 1,000 กว่า pid.
เริ่มด้วยคำสั่งที่เรามักใช้กันบ่อยๆ นึกอะไรไม่ออกก็ ps, top, free โลด
เช่น ดูหน่วยความจำว่าอะไรใช้อยู่บ้าง
$ ps aux --sort -rss | head -n 5
ผู้เขียนขอแบ่งปันประสบการณ์และความรู้จากการใช้ Firefox browser แอปพลิเคชันที่ทำงานใน userspace เคอร์เนล (user profiles) ที่ต้องใช้หน่วยความจำสำหรับตัวมันเอง สำหรับผู้ใช้จำนวนมากบนเซิร์ฟเวอร์เครื่องเดียว (Linux Terminal Deskop)
แต่เมื่อทรัพยากรหมดเกี้ลง (แรมระบบเหลือน้อย) ระบบจะ้ช้า เว้นแต่ user logout ระบบ Linux ถึงจะกู้คืนหน่วยความจำจากสภาวะ OOM (Out of Memory)
อธิบายการทำงานคือ แอพพลิเคชั่นจะต้องขอให้เคอร์เนลจัดสรรหน่วยความจำเพิ่มเติมให้
แต่ถ้าดูจากรูป ไม่มีหน่วยความจำว่าง ทำให้กระบวนการทำงานช้าลง เช่น กด save บันทึกงานใช้เวลานาน, เปิดแท็บใหม่ช้าๆ หรือ้เปิดไฟล์โหลดนาน ฯลฯ
วิธีแก้ปัญหา: (สำคัญคนเงินน้อย) คนมีเงินเลื่อนลงไปอ่านบรรทัดสุดท้าย !!
โดยปกติเคอร์เนลเปิดทางให้แอพพลิเคชั่นขอหน่วยความจำได้เต็มที่ เป้าหมายคือ เพื่อทำให้กระบวนการเร็วขึ้น ซึ่งค่าดีฟอลต์ใน SUSE ลินุกซ์ถูกตั้งค่า overcommit_memory เป็น “0” หมายความว่า เคอร์เนลจะตรวจสอบเพื่อดูว่ามีหน่วยความจำว่างหรือไม่ ก่อนที่จะให้หน่วยความจำเพิ่มกับแอพพลิเคชั่น
พารามิเตอร์คือ 0, 1 และ 2
อธิบายเพิ่มเติม
ถ้า “1” คือไม่ต้องตรวจสอบ จะทำให้ระบบทำงานเหมือนมีหน่วยความจำเหลือๆ
ถ้า “2” คือเคอร์เนลจะปฏิเสธคำขอหน่วยความจำหาก (ไม่มีหน่วยความจำว่าง)
หมายความว่าแอปพลิเคชั่นบางตัวมีโค้ดเขียนดี จะทำงานได้ดีขึ้นหากระบบได้รับการปรับแต่งให้ทำงานว่ามีหน่วยความจำพร้อมเสมอถ้าเทอต้องการ (ที่กระบวนการแอปพลิเคชันต้องการ)
ถ้าเป็น Firefox Browser ก็เปิดไปเถอะ 10 tabs, 20 tabs ก็สบายๆ
จากคำอธิบายพารามิเตอร์ซึ่งวิธีนี้หากกำหนดค่า overcommit_memory เป็น “1” สามารถนำไปสู่สถานการณ์ OMM ได้ (หน่วยความจำไม่เพียงพอ) และจะถูก kernel OOM killer
OOM หมายความว่าหน่วยความจำไม่เพียงพอ และ Killer หมายความว่ากระบวนการจำเป็นต้องถูกฆ่า
ถ้าเป็นระบบ container ก็คือ container กินแรมเกินขีดจำกัดหน่วยความจำใน Memory Cgroup โดยระบบเคอร์เนล Linux จะฆ่ากระบวนการในคอนเทนเนอร์ส่วนจะกำหนดว่าจะทริกเกอร์แบบ auto scale หรือยังไงก็อีกเรื่องครับ
แล้วจะยืนยันได้อย่างไรว่าคอนเทนเนอร์ OOM ถูกฆ่าแล้ว?
เราสามารถใช้คำสั่ง journalctl -k เพื่อตรวจสอบว่าคอนเทนเนอร์ฆ่าโดย OOM ได้
$ journalctl -k
การเปลี่ยนค่า overcommit_memory
สามารถทำโดยพิมพ์คำสั่งecho 1 > /proc/sys/vm/overcommit_memory
[คำแนะนำจากผู้เขียน]
โตแล้วคิดเองได้ 55++ (เลือนลงไปอ่าน “วิธีตรวจสอบและแก้ไขปัญหา”)
วิธีการปรับปรุงประสิทธิภาพ ให้ใช้ค่าดีฟอลต์ “0” สำหรับพารามิเตอร์ overcommit_memory
และเปลี่ยนพารามิเตอร์ overcommit_ratio จากค่าเริ่มต้นของระบบ “50%” เป็นค่าเปอร์เซ็นต์ที่สูงกว่าค่า overcommit_ratio 50
หมายความว่า เคอร์เนลสามารถจัดสรรหน่วยความจำได้มากกว่า 50% ของหน่วยความจำทั้งหมดที่มีอยู่ (ram + swap).
เช่น ในระบบที่มี RAM 8 GB และ swap 2 GB
จำนวนหน่วยความจำที่สามารถระบุตำแหน่ง (addressable) ได้ทั้งหมดจะเท่ากับ 15 GB
สำหรับเปอร์เซ็นต์ overcommit_ratio เริ่มต้นที่ 50 เปลี่ยนเป็น overcommit_ratio เป็น 70%
ซึ่งหมายความว่า จะมีหน่วยความจำจำนวนเพียงพอสำหรับการประมวลผลที่มาก
วิธีตรวจสอบและแก้ไขปัญหา
- แอพพลิเคชั่นของเราต้องการหน่วยความจำจำนวนเท่าไหร่ แล้วคุณด้วยจำนวน users (จัดการให้จบตั้งแต่ทีแรก)
- มอนิเตอร์, วิเคราะห์โค้ด (code analysis) ตรวจสอบการรั่วไหลของหน่วยความจำ เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้หน่วยความจำ เช่น ใช้ cppcheck
- ควบคุมขีดจำกัดหน่วยความจำ หรือ Tuning & Optimization (Memory Tuning and Optimization)
ก่อนปรับจูนทุกๆ ครั้งให้ backup ค่าปัจจุบันไว้ก่อน
$ sysctl -A > /root/sysctl.settings.backup
บอกเคอร์เนลให้ควบคุมการใช้หน่วยความจำสำหรับแอปพลิเคชันตัวไม่สามารถใช้หน่วยความจำสำหรับคำขอแอปพลิเคชันมากเกินไป ในที่สุดฉันก็ได้รวมค่าที่กล่าวถึงเหล่านั้นไว้
แก้ไขในไฟล์ /etc/sysctl.conf เช่น
vm.overcommit_memory = 2
vm.overcommit_ratio = 70
ปกติเคอร์เนลจัดสรรตามหน่วยความจำจริงตอนติดตั้งระบบปฏิบัติการอยู่แล้ว และถูกนำไปใช้โดยอัตโนมัติเมื่อเริ่มต้นระบบ
วิธีแก้ปัญหา: (สำคัญคนมีเงิน)
เพิ่มทรัพยากรให้เพียงพอต่อการใช้งาน ซื้อแรมมาใส่ซะ จบ!
source: https://www.suse.com/c/sles-1112-os-tuning-optimisation-guide-part-1/