TL; DR
สั้นชั่วคราว / คำตอบ
- ง่ายที่สุด : มีพาร์ติชันสลับที่เล็กกว่าและหลีกเลี่ยงเคอร์เนลที่พยายามใช้งานจริงจนถึงขณะที่ไม่มีการ จำกัด หน่วยความจำโดยเรียกใช้กระบวนการจากที่เก็บข้อมูลช้า
- ด้วยการสลับครั้งใหญ่ OOM (จากตัวจัดการหน่วยความจำ) ไม่สามารถดำเนินการได้เร็วพอ ตามปกติแล้วบัญชีตามหน่วยความจำเสมือนและจากประสบการณ์ที่ผ่านมาของฉันไม่ได้ฆ่าสิ่งต่าง ๆ จนกว่าการแลกเปลี่ยนทั้งหมดจะเต็มไปด้วยเหตุนี้ระบบ thrashing และ crawling ...
- ต้องการสลับขนาดใหญ่สำหรับไฮเบอร์เนตหรือไม่
- พยายาม / มีปัญหา : ตั้งค่า ulimits (เช่นตรวจสอบ
ulimit -v
และอาจตั้งค่าขีด จำกัด แบบแข็งหรืออ่อนโดยใช้as
ตัวเลือกในlimits.conf
) สิ่งนี้เคยทำงานได้ดีพอ แต่ด้วยการแนะนำ WebKit gigacage
ทำให้แอปพลิเคชั่นจำนวนมากในขณะนี้คาดว่าจะมีที่อยู่ไม่ จำกัด และไม่สามารถทำงานได้!
- พยายาม / ปัญหา : นโยบาย overcommit และอัตราการใช้เป็นวิธีที่จะพยายามจัดการและบรรเทานี้ (เช่นอื่น
sysctl vm.overcommit_memory
, sysctl vm.overcommit_ratio
แต่วิธีนี้ไม่ได้ผลงานออกมาให้ฉัน
- ยาก / ซับซ้อน : ลองใช้ลำดับความสำคัญ cgroup กับกระบวนการที่สำคัญที่สุด (เช่น ssh) แต่สิ่งนี้ดูเหมือนจะยุ่งยากสำหรับ cgroup v1 (หวังว่า v2 จะทำให้ง่ายขึ้น) ...
ฉันก็ค้นพบ:
- อีกรายการแลกเปลี่ยนสแต็คที่ยืนยันคำแนะนำข้างต้นสำหรับพื้นที่แลกเปลี่ยนที่มีขนาดเล็ก
- คุณสามารถลองทำอะไรบางอย่างเช่นการป้องกัน thrash เพื่อหลีกเลี่ยงสถานการณ์ปัจจุบัน
ทางออกระยะยาว
รอและหวังว่าแพตช์อัปสตรีมบางส่วนจะเข้าสู่เมล็ด distro ที่เสถียร นอกจากนี้หวังว่าผู้จำหน่าย distro จะปรับแต่งค่าเริ่มต้นของเคอร์เนลให้ดีขึ้นและใช้ประโยชน์จากกลุ่มระบบเพื่อจัดลำดับความสำคัญการตอบสนองของ GUI ในรุ่นเดสก์ท็อป
แพทช์ที่น่าสนใจ:
ดังนั้นมันไม่ใช่แค่รหัสพื้นที่ผู้ใช้ที่ไม่ดีและการตั้งค่า / ค่าเริ่มต้น distro ที่ผิด - เคอร์เนลสามารถจัดการกับสิ่งนี้ได้ดีกว่า
ความคิดเห็นเกี่ยวกับตัวเลือกที่พิจารณาแล้ว
1) ปิดการแลกเปลี่ยน
แนะนำอย่างน้อยให้มีการสลับพาร์ติชันเล็ก ๆ ( เราจำเป็นต้องสลับในระบบที่ทันสมัยหรือไม่? ) ปิดการใช้งานแลกเปลี่ยนไม่เพียง แต่ป้องกันการสลับหน้าเว็บที่ไม่ได้ใช้ แต่ก็ยังอาจมีผลต่อค่าเริ่มต้นกลยุทธ์ overcommit เคอร์เนลของการแก้ปัญหาการจัดสรรหน่วยความจำ ( อะไรการวิเคราะห์พฤติกรรมใน Overcommit_memory = 0 หมายถึง? ) เช่นการแก้ปัญหาที่ไม่นับ swap หน้า หากไม่มีการสลับสับเปลี่ยน overcommit ยังคงสามารถใช้งานได้ในโหมดฮิวริสติก (0) หรือโหมดเสมอ (1) แต่การรวมกันของการสลับไม่มีและกลยุทธ์การวางซ้อนที่ไม่เคยมี (2) นั้นน่าจะเป็นแนวคิดที่แย่ ดังนั้นในกรณีส่วนใหญ่ไม่มีการสลับที่จะทำให้ประสิทธิภาพเสียหาย
เช่นลองคิดถึงกระบวนการที่ใช้เวลานานซึ่งเริ่มแรกใช้หน่วยความจำเพื่อทำงานครั้งเดียว แต่ไม่สามารถปล่อยหน่วยความจำนั้นและยังทำงานพื้นหลังต่อไป เคอร์เนลจะต้องใช้ RAM สำหรับสิ่งนั้นจนกว่ากระบวนการจะจบ หากไม่มีการสลับใด ๆ เคอร์เนลจะไม่สามารถคัดออกสิ่งอื่นที่ต้องการใช้ RAM อย่างจริงจัง ลองคิดดูว่าจำนวน devs ขี้เกียจและไม่เพิ่มหน่วยความจำอย่างชัดเจนหลังการใช้งาน
3) ตั้งค่า ulimit หน่วยความจำสูงสุด
ใช้เฉพาะกับแต่ละกระบวนการและอาจเป็นข้อสันนิษฐานที่สมเหตุสมผลว่ากระบวนการไม่ควรร้องขอหน่วยความจำเพิ่มเติมที่ระบบมีอยู่จริง! ดังนั้นจึงอาจมีประโยชน์ในการหยุดกระบวนการที่โดดเดี่ยวไม่ให้เกิดการเฆี่ยนตีในขณะที่ยังคงถูกตั้งค่าอย่างไม่เห็นแก่ตัว
4) รักษาโปรแกรมที่สำคัญ (X11, ทุบตี, ฆ่า, สุดยอด, ... ) ในหน่วยความจำและไม่เคยสลับโปรแกรมเหล่านั้น
เป็นแนวคิดที่ดี แต่โปรแกรมเหล่านั้นจะทำให้หน่วยความจำไม่สามารถใช้งานได้ อาจยอมรับได้หากโปรแกรมร้องขอหน่วยความจำเพียงเล็กน้อยเท่านั้น
systemd 232 releaseเพิ่งเพิ่มตัวเลือกบางอย่างที่ทำให้เป็นไปได้: ฉันคิดว่าสามารถใช้ 'MemorySwapMax = 0' เพื่อป้องกันยูนิต (บริการ) เช่น ssh ที่มีหน่วยความจำใด ๆ
อย่างไรก็ตามความสามารถในการจัดลำดับความสำคัญการเข้าถึงหน่วยความจำจะดีกว่า
คำอธิบายที่ยาว
เคอร์เนล linux ได้รับการปรับแต่งให้ดีขึ้นสำหรับปริมาณงานเซิร์ฟเวอร์ดังนั้นการตอบสนองของ GUI จึงเป็นเรื่องที่น่าเศร้ารอง ... การตั้งค่าการจัดการหน่วยความจำเคอร์เนลใน Ubuntu Desktop เวอร์ชั่น 16.04 LTS ดูเหมือนจะไม่แตกต่างจากเซิร์ฟเวอร์รุ่นอื่น มันยังตรงกับค่าเริ่มต้นใน RHEL / CentOS 7.2 ซึ่งโดยปกติจะใช้เป็นเซิร์ฟเวอร์
OOM, ulimit และทำการแลกเปลี่ยนความซื่อสัตย์เพื่อการตอบสนอง
สลับ thrashing (เมื่อชุดหน่วยความจำที่ใช้งานได้เช่นเพจที่กำลังอ่านและเขียนลงในกรอบเวลาที่สั้นเกินกว่าแรมจริง) จะล็อกหน่วยเก็บ I / O เสมอ - ไม่มีเคอร์เนลพ่อมดสามารถบันทึกระบบจากสิ่งนี้ได้โดยไม่ต้องฆ่ากระบวนการ หรือสอง ...
ฉันหวังว่าการปรับแต่ง Linux OOM จะมาพร้อมกับเคอร์เนลที่เพิ่งทราบว่าชุดการทำงานนี้เกินกว่าสถานการณ์หน่วยความจำกายภาพและฆ่ากระบวนการ เมื่อไม่มีปัญหาเกิดขึ้น ปัญหาคือด้วยพาร์ทิชัน swap ขนาดใหญ่มันสามารถดูราวกับว่าระบบยังคงมี headroom ในขณะที่เคอร์เนลมีความมุ่งมั่นอย่างมากและยังคงทำหน้าที่ร้องขอหน่วยความจำ แต่ชุดการทำงานสามารถกระจายไปสู่ swap ได้อย่างมีประสิทธิภาพ มันคือแรม
บนเซิร์ฟเวอร์ยอมรับการลงโทษประสิทธิภาพของการฟาดสำหรับการกำหนดช้าไม่สูญเสียข้อมูลการแลกเปลี่ยน บนเดสก์ท็อปการแลกเปลี่ยนจะแตกต่างกันและผู้ใช้ต้องการความสูญเสียข้อมูลเล็กน้อย (กระบวนการเสียสละ) เพื่อให้สิ่งต่าง ๆ ตอบสนอง
นี่คือการเปรียบเทียบตลกที่ดีเกี่ยวกับ OOM: oom_pardon, aka ไม่ฆ่า xlock ของฉัน
อนึ่งOOMScoreAdjust
เป็นอีกตัวเลือก systemd น้ำหนักความช่วยเหลือและหลีกเลี่ยงการ OOM ฆ่ากระบวนการถือว่ามีความสำคัญมากขึ้น
บัฟเฟอร์การเขียนกลับ
ฉันคิดว่า " ทำให้การเขียนแบ็คกราวนด์ไม่ได้ดูด " จะช่วยหลีกเลี่ยงปัญหาบางอย่างที่กระบวนการแฮ็ก RAM ทำให้เกิดการสลับออกอีกครั้ง (เขียนไปยังดิสก์) และการเขียนจำนวนมากไปยังแผงลอยบนดิสก์ มันไม่ได้เป็นสาเหตุของปัญหาการแย่งชิงตัวเอง แต่มันจะเพิ่มการย่อยสลายโดยรวมในการตอบสนอง
ข้อ จำกัด ulimits
ปัญหาหนึ่งที่เกิดขึ้นกับ ulimits คือข้อ จำกัด ทางบัญชีจะใช้กับพื้นที่ที่อยู่หน่วยความจำเสมือน (ซึ่งหมายถึงการรวมทั้งพื้นที่ทางกายภาพและพื้นที่สว็อป) ตามman limits.conf
:
rss
maximum resident set size (KB) (Ignored in Linux 2.4.30 and
higher)
ดังนั้นการตั้งค่า ulimit ให้นำไปใช้กับการใช้ RAM ทางกายภาพจึงไม่สามารถใช้งานได้อีกต่อไป ด้วยเหตุนี้
as
address space limit (KB)
น่าจะเป็น tunable ที่เคารพเท่านั้น
น่าเสียดายที่รายละเอียดเพิ่มเติมจากตัวอย่างของ WebKit / Gnome แอปพลิเคชันบางตัวไม่สามารถทำงานได้หากการจัดสรรพื้นที่ที่อยู่เสมือนถูก จำกัด
กลุ่ม cg จะช่วยในอนาคต?
ปัจจุบันดูเหมือนว่าจะยุ่งยาก แต่เป็นไปได้ที่จะเปิดใช้งานแฟล็ก cgroup ของเคอร์เนลcgroup_enable=memory swapaccount=1
(เช่นใน grub config) แล้วลองใช้คอนโทรลเลอร์หน่วยความจำ cgroup เพื่อ จำกัด การใช้หน่วยความจำ
กลุ่ม cg มีคุณสมบัติ จำกัด หน่วยความจำขั้นสูงเพิ่มเติมแล้วตัวเลือก 'ulimit' CGroup v2บันทึกคำใบ้ที่พยายามปรับปรุงเกี่ยวกับวิธีการทำงานของ ulimits
การรวมหน่วยความจำ + การสลับบัญชีและการ จำกัด จะถูกแทนที่ด้วยการควบคุมพื้นที่สวอปอย่างแท้จริง
ตัวเลือก CGroup สามารถตั้งค่าผ่านตัวเลือกการควบคุมทรัพยากร systemd เช่น:
ตัวเลือกที่มีประโยชน์อื่น ๆ อาจจะเป็น
สิ่งเหล่านี้มีข้อบกพร่อง:
- เหนือศีรษะ เอกสารนักเทียบท่าในปัจจุบันกล่าวโดยสังเขปกล่าวถึงการใช้หน่วยความจำเพิ่มเติม 1% และประสิทธิภาพการทำงานลดลง 10% (อาจเกี่ยวข้องกับการดำเนินการจัดสรรหน่วยความจำ - มันไม่ได้ระบุจริง ๆ )
- สิ่ง Cgroup / systemd ได้รับการทำงานอย่างหนักเมื่อไม่นานมานี้ดังนั้นฟลักซ์อัพสตรีมจึงแสดงให้เห็นว่าผู้จำหน่ายลีนุกซ์ดิสทริบิวเตอร์อาจรอให้มันยุติก่อน
ในCGroup v2พวกเขาแนะนำว่าmemory.high
ควรเป็นตัวเลือกที่ดีในการเร่งความเร็วและจัดการหน่วยความจำที่ใช้โดยกลุ่มกระบวนการ อย่างไรก็ตามคำพูดนี้แสดงให้เห็นว่าการตรวจสอบสถานการณ์ความกดดันของหน่วยความจำจำเป็นต้องใช้งานมากขึ้น
การวัดความดันหน่วยความจำ - ปริมาณงานที่ได้รับผลกระทบเนื่องจากหน่วยความจำไม่เพียงพอ - มีความจำเป็นเพื่อกำหนดว่าเวิร์กโหลดต้องการหน่วยความจำเพิ่มหรือไม่ น่าเสียดายที่กลไกการตรวจสอบความดันหน่วยความจำยังไม่ได้ใช้งาน
เนื่องจากเครื่องมือพื้นที่ผู้ใช้ systemd และ cgroup นั้นซับซ้อนฉันไม่พบวิธีง่ายๆในการตั้งค่าบางอย่างที่เหมาะสมและใช้ประโยชน์จากสิ่งนี้ต่อไป เอกสาร cgroup และ systemd สำหรับ Ubuntu นั้นยอดเยี่ยม การทำงานในอนาคตควรมีไว้สำหรับ distro ที่มีรุ่นเดสก์ท็อปเพื่อใช้ประโยชน์จาก cgroups และ systemd เพื่อให้ภายใต้ความกดดันหน่วยความจำสูง ssh และส่วนประกอบ X-Server / window manager ได้รับความสำคัญในการเข้าถึง CPU, RAM จริงและหน่วยเก็บข้อมูล IO การแลกเปลี่ยนไม่ว่าง คุณลักษณะของ CPU และ I / O ของเคอร์เนลมีมานานแล้ว ดูเหมือนว่าจะเป็นการเข้าถึงลำดับความสำคัญกับ RAM จริงที่ขาดหายไป
อย่างไรก็ตามไม่ได้ตั้งค่าลำดับความสำคัญของ CPU และ IO อย่างเหมาะสม! เมื่อฉันตรวจสอบข้อ จำกัด ของ systemd cgroup, cpu ที่ใช้ร่วมกัน, และอื่น ๆ , เท่าที่ฉันสามารถบอกได้, Ubuntu ไม่ได้อบในการกำหนดล่วงหน้าที่กำหนดไว้ล่วงหน้า. เช่นฉันวิ่ง:
systemctl show dev-mapper-Ubuntu\x2dswap.swap
ฉันเปรียบเทียบสิ่งนั้นกับเอาต์พุตเดียวกันสำหรับ ssh, samba, gdm และ nginx สิ่งสำคัญเช่น GUI และคอนโซลผู้ดูแลระบบระยะไกลต้องต่อสู้อย่างเท่าเทียมกันกับกระบวนการอื่น ๆ ทั้งหมดเมื่อเกิดการเฆี่ยนตี
ตัวอย่างการ จำกัด หน่วยความจำที่ฉันมีในระบบ RAM 16GB
ฉันต้องการเปิดใช้งานไฮเบอร์เนตดังนั้นฉันจึงจำเป็นต้องมีพาร์ทิชันสลับขนาดใหญ่ ดังนั้นการพยายามบรรเทาด้วย ulimits เป็นต้น
ulimit
ฉันใส่* hard as 16777216
ใน/etc/security/limits.d/mem.conf
นั้นว่าไม่มีกระบวนการเดียวจะได้รับอนุญาตให้ขอหน่วยความจำมากกว่าที่เป็นไปได้ทางร่างกาย ฉันจะไม่ขัดขวางการฟาดฟันทั้งหมด แต่ไม่มีเพียงกระบวนการเดียวที่ใช้หน่วยความจำโลภหรือการรั่วไหลของหน่วยความจำ เช่นฉันเห็นgnome-contacts
หน่วยความจำ 8GB ขึ้นไปเมื่อทำสิ่งต่าง ๆ เช่นการอัปเดตรายการที่อยู่ร่วมจากเซิร์ฟเวอร์แลกเปลี่ยน ...
ตามที่เห็นด้วยulimit -S -v
distros จำนวนมากมีขีด จำกัด ที่แข็งและอ่อนนุ่มนี้ตามที่กำหนดไว้ในทางทฤษฎีแล้วกระบวนการอาจจบลงด้วยการร้องขอหน่วยความจำจำนวนมาก แต่ใช้หน่วยย่อยอย่างแข็งขันเท่านั้นและทำงานอย่างมีความสุข ระบบมี 16GB เท่านั้น ขีด จำกัด ฮาร์ดด้านบนจะทำให้กระบวนการที่อาจทำงานได้ดีเพื่อยกเลิกเมื่อเคอร์เนลปฏิเสธการร้องขอหน่วยความจำแบบเก็งกำไรโลภ
อย่างไรก็ตามมันยังจับสิ่งที่ไม่ดีเช่นที่อยู่ติดต่อของ gnome แทนการสูญเสียการตอบสนองบนเดสก์ท็อปของฉันฉันได้รับข้อผิดพลาด "หน่วยความจำว่างไม่เพียงพอ":
ภาวะแทรกซ้อนการตั้งค่า ulimit สำหรับพื้นที่ที่อยู่ (หน่วยความจำเสมือน)
น่าเสียดายที่นักพัฒนาบางคนชอบแกล้งหน่วยความจำเสมือนเป็นทรัพยากรที่ไม่มีที่สิ้นสุดและการตั้งค่า ulimit บนหน่วยความจำเสมือนอาจทำให้แอพบางตัวพัง เช่น WebKit (ซึ่งบางแอพขึ้นอยู่กับแอป gnome) ได้เพิ่มgigacage
คุณสมบัติความปลอดภัยซึ่งพยายามที่จะจัดสรรหน่วยความจำเสมือนจำนวนบ้าและFATAL: Could not allocate gigacage memory
ข้อผิดพลาดโดยมีคำใบ้ทะลึ่งMake sure you have not set a virtual memory limit
เกิดขึ้น การทำงานรอบ ๆGIGACAGE_ENABLED=no
ลืมประโยชน์ด้านความปลอดภัย แต่ในทำนองเดียวกันการไม่อนุญาตให้ จำกัด การจัดสรรหน่วยความจำเสมือนก็จะลืมคุณสมบัติด้านความปลอดภัย (เช่นการควบคุมทรัพยากรที่สามารถป้องกันการปฏิเสธการให้บริการ) ดูเหมือนว่าระหว่าง gigacage และ gnome devs พวกเขาดูเหมือนจะลืมว่าการจัดสรรหน่วยความจำที่ จำกัด นั้นเป็นตัวควบคุมความปลอดภัย และน่าเศร้าที่ฉันสังเกตเห็นแอปพลิเคชั่นคำพังเพยที่พึ่งพา gigacage ไม่ต้องกังวลกับการขอวงเงินที่สูงกว่าอย่างชัดเจนดังนั้นแม้แต่การ จำกัด ที่อ่อนนุ่มก็ทำให้สิ่งต่าง ๆ แตกในกรณีนี้
หากเคอร์เนลทำงานได้ดีกว่าในการปฏิเสธการจัดสรรหน่วยความจำตามการใช้หน่วยความจำถิ่นที่อยู่แทนการใช้หน่วยความจำเสมือนการแกล้งหน่วยความจำเสมือนนั้นไม่ จำกัด จะมีอันตรายน้อยกว่า
overcommit
หากคุณต้องการให้แอปพลิเคชันถูกปฏิเสธการเข้าถึงหน่วยความจำและต้องการหยุดเขียนทับให้ใช้คำสั่งด้านล่างเพื่อทดสอบว่าระบบของคุณทำงานอย่างไรเมื่ออยู่ภายใต้ความกดดันหน่วยความจำสูง
ในกรณีของฉันอัตราส่วนการกระทำเริ่มต้นคือ:
$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
แต่จะมีผลบังคับใช้อย่างเต็มรูปแบบเมื่อเปลี่ยนนโยบายเพื่อปิดใช้งานการเขียนทับมากเกินไปและใช้อัตราส่วน
sudo sysctl -w vm.overcommit_memory=2
อัตราส่วนโดยนัยของหน่วยความจำ 24GB เท่านั้นที่สามารถจัดสรรโดยรวมได้ (RAM 16GB * 0.5 + 16GB SWAP) ดังนั้นฉันอาจไม่เคยเห็น OOM ปรากฏขึ้นและมีโอกาสน้อยกว่าที่จะมีกระบวนการเข้าถึงหน่วยความจำอย่างต่อเนื่องในการสลับ แต่ฉันจะเสียสละประสิทธิภาพของระบบโดยรวมด้วย
นี่จะทำให้แอปพลิเคชั่นจำนวนมากหยุดทำงานเนื่องจากเป็นเรื่องปกติที่ devs จะไม่จัดการกับระบบปฏิบัติการอย่างปฏิเสธคำขอการจัดสรรหน่วยความจำ มันซื้อขายความเสี่ยงเป็นครั้งคราวของการดึงออกมาเนื่องจากการ thrashing (ปล่อยงานทั้งหมดของคุณหลังจากการรีเซ็ตฮาร์ด) เป็นความเสี่ยงที่พบบ่อยของแอพต่าง ๆ ที่ล้มเหลว ในการทดสอบของฉันมันไม่ได้ช่วยอะไรมากนักเนื่องจากเดสก์ท็อปล้มเหลวเมื่อระบบอยู่ภายใต้แรงกดดันหน่วยความจำและไม่สามารถจัดสรรหน่วยความจำได้ อย่างไรก็ตามอย่างน้อยคอนโซลและ SSH ยังคงทำงานได้
หน่วยความจำการโอเวอร์เมตของ VM ทำงานอย่างไรมีข้อมูลมากขึ้น
ฉันเลือกที่จะกลับไปใช้ค่าเริ่มต้นสำหรับสิ่งนี้sudo sysctl -w vm.overcommit_memory=0
เนื่องจากสแต็กแบบกราฟิกบนเดสก์ท็อปทั้งหมดและแอปพลิเคชันที่อยู่ในนั้นขัดข้อง