ส่วนที่ 9.6 "Overcommit และ OOM" ในเอกสารที่ @dunxd กล่าวถึงเป็นภาพกราฟิกโดยเฉพาะอย่างยิ่งอันตรายของการอนุญาตให้มีคำสั่งเกินความจำเป็น อย่างไรก็ตามสิ่ง80
ที่ฉันสนใจก็ดูน่าสนใจเช่นกัน
สิ่งที่ฉันพบคือการที่overcommit_ratio
ส่งผลกระทบต่อ RAM ทั้งหมดที่มีอยู่สำหรับกระบวนการทั้งหมด กระบวนการรูทไม่ได้รับการปฏิบัติแตกต่างจากกระบวนการผู้ใช้ทั่วไป
การตั้งค่าอัตราส่วนเป็น100
หรือน้อยกว่านั้นควรให้ความหมายแบบคลาสสิกที่ค่าส่งคืนmalloc/sbrk
มีความน่าเชื่อถือ การตั้งค่าอัตราส่วนต่ำกว่า100
อาจเป็นวิธีสำรอง RAM เพิ่มเติมสำหรับกิจกรรมที่ไม่ได้ดำเนินการเช่นแคชเป็นต้น
ดังนั้นในคอมพิวเตอร์ของฉันที่มี RAM 24 GiB โดยมีการปิดการใช้งาน swap มีการใช้งาน 9 GiB พร้อมการtop
แสดง
Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers
Swap: 0k total, 0k used, 0k free, 241804k cached
ต่อไปนี้คือovercommit_ratio
การตั้งค่าบางอย่างและจำนวนแรมที่โปรแกรม ram-Consumer ของฉันสามารถคว้าmalloc
ได้
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
เรียกใช้หลายรายการพร้อมกันแม้ว่าจะเป็นผู้ใช้รูท แต่ก็ไม่ได้เปลี่ยนยอดรวมที่พวกเขาใช้ไปด้วยกัน เป็นเรื่องที่น่าสนใจที่ไม่สามารถบริโภค 3+ GiB ล่าสุดหรือมากกว่านั้น free
ไม่ได้วางต่ำกว่าสิ่งที่แสดงให้เห็นที่นี่:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
การทดลองยุ่งเหยิง - อะไรก็ตามที่ใช้ malloc ในขณะที่ RAM ทั้งหมดที่ใช้งานมีแนวโน้มที่จะผิดพลาดเนื่องจากโปรแกรมเมอร์จำนวนมากกลัวการตรวจสอบความล้มเหลว malloc ใน C ห้องสมุดเก็บรวบรวมยอดนิยมบางแห่งไม่สนใจมันทั้งหมดและ C ++ และภาษาอื่น ๆ แย่ลง
การนำไปใช้งานในช่วงแรกของ RAM ในจินตนาการที่ฉันเห็นคือจัดการกับกรณีที่เฉพาะเจาะจงมากซึ่งกระบวนการขนาดใหญ่เดียว - กล่าวว่า 51% + ของหน่วยความจำที่มีอยู่ - จำเป็นต้องใช้fork()
เพื่อexec()
สนับสนุนโปรแกรมบางโปรแกรมซึ่งมักจะเล็กกว่ามาก OS ที่มีซีแมนทิกส์ copy-on-write จะอนุญาตfork()
แต่ด้วยเงื่อนไขที่ว่าหากกระบวนการที่แยกจากกันพยายามแก้ไขหน้าหน่วยความจำมากเกินไป (แต่ละอันนั้นจะต้องถูกสร้างอินสแตนซ์เป็นหน้าใหม่โดยไม่ขึ้นอยู่กับกระบวนการขนาดใหญ่เริ่มต้น) มันจะจบลงด้วยการถูกฆ่าตาย กระบวนการผู้ปกครองตกอยู่ในอันตรายหากจัดสรรหน่วยความจำเพิ่มเติมและสามารถจัดการกับการเรียกใช้ในบางกรณีเพียงแค่รอสักครู่สำหรับกระบวนการอื่นที่จะตายแล้วดำเนินการต่อ กระบวนการลูกมักจะแทนที่ตัวเองด้วยโปรแกรม (มักจะเล็กกว่า) ผ่านทางexec()
และจากนั้นก็เป็นอิสระจากเงื่อนไข
แนวคิด overcommit ของ Linux เป็นวิธีการที่ยอดเยี่ยมในการอนุญาตให้ทั้งสองfork()
เกิดขึ้นรวมถึงการอนุญาตให้กระบวนการเดียวเพื่อสร้างภาพรวมที่ใหญ่โต เสียชีวิต OOM นักฆ่าที่เกิดจากการถ่ายทอดสดเกิดขึ้นแม้กับโปรแกรมที่ทำจัดสรรหน่วยความจำจับความรับผิดชอบ ฉันเกลียดการ overcommit ทั่วทั้งระบบโดยทั่วไปและโดยเฉพาะอย่างยิ่ง oom-killer - มันสนับสนุนแนวทางการดูแลหน่วยความจำที่ติดมารและอาจทำให้ห้องสมุดและผ่านพวกเขาทุกแอปที่ใช้พวกเขา
ฉันขอแนะนำให้ตั้งค่าอัตราส่วนเป็น 100 และมีพาร์ติชันสลับเช่นกันซึ่งโดยทั่วไปแล้วจะจบลงด้วยการใช้งานโดยกระบวนการขนาดใหญ่ - ซึ่งมักใช้เพียงเศษเสี้ยวเล็ก ๆ ของส่วนของตัวเองที่ถูกยัดเข้าไปใน swap แล้ว ปกป้องกระบวนการส่วนใหญ่จากความผิดพลาดของนักฆ่า OOM สิ่งนี้จะช่วยให้เว็บเซิร์ฟเวอร์ของคุณปลอดภัยจากการเสียชีวิตแบบสุ่มและหากมีการเขียนเพื่อจัดการอย่างmalloc
รับผิดชอบแม้จะปลอดภัยจากการฆ่าตัวเอง (แต่ไม่ต้องเดิมพันตอนหลัง)
นั่นหมายความว่าฉันกำลังใช้สิ่งนี้ใน /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100