วิธีเชื่องการตอบสนองของ Linux หน่วยความจำและการแบ่งหน้า


27

คำถามแรกในโอเวอร์โฟลว์ =) ... +100 เงินรางวัล ไม่สามารถนึกถึงบางสิ่งที่ฉันห่วงใยมาจนถึงปัจจุบัน:

ฉันเบื่อกับสถานะการตอบสนองบนเดสก์ท็อปของ Linux เช่นhttp://brainstorm.ubuntu.com/item/85/ - ในสถานการณ์ที่มี RAM ต่ำฟรีหรือสถานการณ์ที่มีปริมาณดิสก์สูงระบบจะช้าลง การรวบรวมข้อมูล ; นี่เป็นสิ่งที่แย่มากสำหรับแอปพลิเคชั่นที่ต้องมีประสิทธิภาพ นอกจากนี้ UI ไม่ตอบสนองอย่างสมบูรณ์ เปรียบเทียบสิ่งนี้กับ OS X ซึ่งหากแอปพลิเคชันเป็นทรัพยากรที่ hogging เราสามารถคลิกเพื่อบังคับให้ออกจากตัวเลือกขณะที่ใน Linux ฉันไม่สามารถแม้แต่แท็บ alt หรือแท็บเดสก์ท็อปหรือแม้แต่ ctrl-alt-f1 เทอร์มินัล - ดีฉันทำได้ใช้เวลาประมาณ 1-2 นาทีต่อการใช้งาน

ฉันใช้ gkrellm เพื่อที่ฉันจะได้เห็นสถานการณ์ในขณะที่มันแผ่ออกไป โดยทั่วไปแล้วการใช้หน่วยความจำจะค่อนข้างสูงหรือปริมาณงานของดิสก์เพิ่มขึ้นอย่างรวดเร็ว

มันไม่ได้เป็นฮาร์ดแวร์ที่ไม่ดีมี quad-core 2.6GHz และ 4GB 800MHz DDR2 RAM (จะมี 6GB แต่เนื่องจากความไม่ลงรอยกันของฮาร์ดแวร์ไม่สามารถผสมและตรงกับชุดเก่า) ปัญหานี้อาจหายไปเมื่อฉันหลีกเลี่ยงการใช้ RAM เพิ่มขึ้น แต่ฉันไม่รู้สึกว่าเป็นหัวใจของปัญหา ฉันยังมีการสลับสองพาร์ติชั่นในดิสก์ที่แตกต่างกัน

ฉันรู้สึกว่าปัญหาเป็นสามเท่า:

  • โปรแกรมที่ควบคุมไม่ได้ซึ่งมีหน่วยความจำจำนวนมากต้องมีกฎหมายกำหนดไว้สำหรับโปรแกรมเหล่านี้โดยมีข้อ จำกัด
    • (เช่นแท็บบน Chrome แต่ละอันมีขนาด 20-50MB บางส่วนสามารถใช้หลายร้อย MB)
    • (เช่นโปรแกรมอื่น ๆ เช่น update-db และตัวทำดัชนีที่ฉันต้องปิดการใช้งานและลบออกจาก cron เพราะพวกเขาทำให้ระบบช้าลงในการรวบรวมข้อมูลทุกครั้งที่พวกเขาวิ่งเป็นต้น)
  • สิ่งที่น่ากลัวเกิดขึ้นในเคอร์เนลหรือการช่วงชิงบัสในบางประเภทเช่นสถานการณ์ที่ปริมาณการรับส่งข้อมูลบนดิสก์สูงทำให้ระบบทั้งระบบช้าลงในการรวบรวมข้อมูล (อาจเป็นการยกเลิกโปรแกรมสำคัญ ๆ )
  • เคอร์เนลไม่ได้ให้ความสำคัญกับ UI หรือโปรแกรมที่สำคัญในแง่ของทรัพยากรเช่นหน่วยความจำการเพจหรือแม้แต่การใช้งานตัวประมวลผล

upvotes ไปที่:

ฉันกำลังมองหาวิธีการแก้ปัญหาที่ทุกโปรแกรมดังกล่าวหายไป โดยเฉพาะอย่างยิ่งฉันกำลังมองหาวิธีการแก้ปัญหาที่กระบวนการจะชะลอตัวลงตามสัดส่วนในขณะที่ระบบและโปรแกรมอื่น ๆ ยังคงไม่ได้รับผลกระทบและตอบสนองนานพอที่จะฆ่าบางสิ่งบางอย่างด้วยตนเอง นอกจากนี้กระบวนการจัดการหน้าต่าง (และสิ่งอื่นใดที่อาจส่งผลกระทบต่อการตอบสนองของ UI) ควรตอบสนองในทุกสถานการณ์

โดยเฉพาะอย่างยิ่งฉันรู้สึกทึ่งกับ/etc/security/limits.conf( man limits.conf) แต่ฉันกังวลว่านี่เป็นเพียงการควบคุมต่อผู้ใช้เท่านั้นและตัวอย่างความคิดเห็นในไฟล์ดูเหมือนจะค่อนข้างทึบในแง่ของคำอธิบายหรือจะเริ่มต้นที่ไหน ฉันหวังว่าlimits.confผลงาน แต่จะไม่แปลกใจถ้ามันไม่ได้ทำงานหรือถ้ามันไม่ใช่วิธีการแก้ปัญหาที่เหมาะสมสำหรับปัญหาของฉันหรือเป็นเม็ดที่ฉันพยายามที่จะบรรลุ ต่อกระบวนการชื่อlimits.confจะเหมาะสมมติว่าอีกครั้ง limit.conf ทำงาน ฉันยินดีที่จะลองใช้ข้อ จำกัด ต่าง ๆ ที่มีให้เพื่อทดสอบว่าใช้งานได้หรือไม่แม้ว่าฉันจะเปิดรับโซลูชั่นทั้งหมดในตอนนี้

มันอาจมีประโยชน์ที่จะมีความเข้าใจในวิธีที่ OS X จัดการเพื่อให้ทันกับการตอบสนองของ UI ที่ดีเช่นนั้น

ฉันได้ปรับแต่ง/tmpโฟลเดอร์แคชและโฟลเดอร์ของฉันtmpfsแล้วและในการใช้งานดิสก์ทั่วไปอยู่ใกล้ศูนย์

หัวข้อที่เกี่ยวข้องกับ Vaguely:

  • overcommit หน่วยความจำ

คำตอบฉันไม่คิดว่าจะทำงาน:

  • swapoff (สิ่งนี้ยังช่วยให้โปรแกรมหมูหน่วยความจำหลุดพ้นจากการฆาตกรรมได้และระบบจะแช่แข็งอย่างถาวรหากหน่วยความจำไม่ดี - ผู้ที่แนะนำการบิดที่เรียกใช้ OOM-killer ก่อนหน้านี้จะทำการสลับและกำหนดเป้าหมายโปรแกรมเฉพาะ)
  • echo ?? > /sys/.../swappiness (ไม่มีผลกระทบที่มองเห็นได้)
  • nice (ไม่เคยทำงาน)
  • ionice (ไม่เคยสังเกตเห็นความแตกต่าง)
  • selinux (โปรแกรมที่เข้ากันไม่ได้ดูเหมือนจะเป็นฝันร้าย)
  • ลินุกซ์เรียลไทม์คือสามารถขัดจังหวะเคอร์เนล (ไม่ต้องการจัดการกับการรวบรวมและการปรับปรุงเคอร์เนลที่กำหนดเอง; อาจจะไม่เป็นไรถ้ามันได้ย้ายไปที่ที่เก็บ)
  • * * * *

อืมดูเหมือนว่าฉันจะไม่ได้รับความโปรดปราน ฉันเดาว่าลิงก์นั้นไม่ปรากฏขึ้นเป็นเวลา 48 ชั่วโมงใช่ไหม ... ฉันจะโพสต์ค่าหัวกับชื่อเสียงทั้งหมดที่ฉันได้รับมาแล้ว
user76871

1
+1 นี่คือปัญหาใหญ่ที่สุดเดียวที่ฉันมีกับเดสก์ท็อป Linux ในแต่ละวัน ฉันมีอาการค้างเป็นครั้งคราวบางทีทุกๆสองสัปดาห์ แต่สิ่งเหล่านี้ไม่เพียงพอที่จะทำให้เกิดความรำคาญเป็นพิเศษ อย่างไรก็ตามดูเหมือนว่าจะมีปัญหากับแอปพลิเคชันที่มีตามที่คุณกล่าวว่าการใช้งานIOหนัก: แอปพลิเคชันที่มีการใช้งาน CPU สูงจะไม่มีผลต่อประสิทธิภาพของระบบทั่วไปเพียงเล็กน้อย ไม่ทราบเกี่ยวกับ ionice ดูเหมือนว่ามันจะเป็นทางออกที่ถูกต้องสำหรับปัญหานี้หากมันทำงานได้อย่างถูกต้อง
crazy2be

1
3 ปีต่อมาและนี่ยังคงเป็นปัญหาบน Linux @ crazy2be หรือ user76871 ฉันไม่คิดว่าคุณจะพบทางออกในขณะนี้?
Glutanimate

@ Glutanimate: ใช่, RAM จริง 32GB และไม่น้อย (อาจจะเป็น 16GB ... สิ่งนี้ไม่ได้แก้ไขการไม่ตอบสนองเนื่องจาก CPU สูงหรือการขัดจังหวะหรืออะไรก็ตาม แต่จะป้องกันการไม่ตอบสนองในสถานการณ์ที่มีหน่วยความจำต่ำ
user76871

คำตอบ:


6

ดูเหมือนว่าระบบของคุณจะเปลี่ยนไปอย่างมาก การใช้vmstat 1อาจเปิดเผยรายละเอียดบางอย่าง - เพียงแค่ปล่อยให้มันรันในหน้าต่างเทอร์มินัลแล้วสลับไปใช้เมื่อการชะลอตัวเริ่มขึ้น

แทนที่จะใส่ / tmp และ "cache" ลงใน tmpfs ฉันจะใช้ระบบไฟล์ดิสก์ปกติที่เมาท์พร้อมnoatimeตัวเลือก ข้อมูลที่ใช้บ่อยจะอยู่ในแคชต่อไปและข้อมูลเก่าสามารถเขียนลงดิสก์เพื่อเพิ่ม RAM สำหรับแอปพลิเคชัน หาก / tmp และ / หรือแคชใหญ่ขึ้นสิ่งนี้อาจช่วยได้มาก


1
+1 noatimeสำหรับการกล่าวขวัญ
LawrenceC

ขอบคุณที่พูดถึงnoatimeแต่น่าเสียดายที่ฉันเคยใช้ตัวเลือกการเมานต์นั้นและฉันไม่คิดว่ามันจะช่วยได้มากในการตอบสนอง (แม้ว่าจะช่วยให้ตันเพื่อให้แน่ใจว่าดิสก์ไม่ทำงานหนักเกินไป); เพียงเพื่อให้แน่ใจว่าฉันเปิดใช้งานใหม่เวลากลางคืนในการตั้งค่าปัจจุบันของฉัน การมี non-tmpfs พร้อม noatime นั้นดูค่อนข้างแปลกเพราะฉันยังคงจินตนาการว่างานเขียนขนาดใหญ่จะต้องเกิดขึ้น
user76871

+1, พยายามvmstat 1- มีประโยชน์อย่างมากในการวินิจฉัยการกอดกัน, ในความเป็นจริง, ปัญหาส่วนใหญ่ของปัญหาหลัก
76871

2
อุ๊ยตาย ไม่เคยเห็นระบบ linux ที่ต้องการการแลกเปลี่ยนอย่างหนัก คุณได้ตรวจสอบกับdf -mจำนวนหน่วยความจำที่ใช้ในระบบไฟล์ tmpfs หรือไม่? บางสิ่งบางอย่างจะกิน RAM ของคุณค่อนข้างเร็ว
Turbo J

ขอบคุณสำหรับคำแนะนำและสอนฉันเกี่ยวกับ-mตัวเลือก น่าเสียดายที่df -h -mดูเหมือนว่าจะมีหน่วยความจำของฉันอยู่เพียง 100MB tmpfsดังนั้นฉันสงสัยว่ามันเกี่ยวข้องกับสิ่งใดหากใช้หน่วยความจำสำหรับ tmpfs และแคช สิ่งนี้ก็ไม่ได้แปลกไปเหมือนกัน ฉันมีมันเกิดขึ้นในการกระจายหลายเมื่อ RAM ของพวกเขาถูกผลักไปใกล้ขีด จำกัด
user76871

5

ฉันไม่ใช่นักพัฒนาเคอร์เนล แต่ฉันใช้เวลาหลายปีในการแก้ไขปัญหานี้เพราะฉันพบเจอปัญหานี้หลายครั้ง จริง ๆ แล้วฉันได้คำอุปมาสำหรับสถานการณ์ทั้งหมดดังนั้นให้ฉันบอกคุณว่า ฉันจะสมมติในเรื่องของฉันว่าไม่มีอะไรอย่าง "สลับ" การสลับไม่เข้าท่ากับ RAM ขนาด 32 GB ในปัจจุบัน

ลองนึกภาพพื้นที่ใกล้เคียงของคุณที่มีน้ำเชื่อมต่อกับแต่ละอาคารผ่านท่อและเมืองจำเป็นต้องจัดการความจุ สมมติว่าคุณมีการผลิตน้ำเพียง 100 หน่วยต่อวินาที (และความจุที่ไม่ได้ใช้ทั้งหมดจะสูญเปล่าเพราะคุณไม่มีถังเก็บน้ำ) แต่ละบ้าน (home = แอปเล็ก ๆ น้อย ๆ เทอร์มินัลวิดเจ็ตนาฬิกาและอื่น ๆ ) ต้องใช้น้ำ 1 หน่วยต่อวินาที ทั้งหมดนี้ดีและดีเพราะประชากรของคุณเป็น 90 ดังนั้นทุกคนจึงได้รับน้ำเพียงพอ

ตอนนี้นายกเทศมนตรี (= คุณ) ตัดสินใจว่าคุณต้องการเปิดร้านอาหารขนาดใหญ่ (= เบราว์เซอร์) ร้านอาหารนี้จะเป็นที่ตั้งของพ่อครัวหลายคน (= แท็บเบราว์เซอร์) ผู้ปรุงแต่ละคนต้องการน้ำ 1 หน่วยต่อวินาที คุณเริ่มต้นด้วยพ่อครัว 10 คนดังนั้นปริมาณการใช้น้ำโดยรวมสำหรับพื้นที่ใกล้เคียงทั้งหมดคือ 100 หน่วยน้ำซึ่งยังคงดีอยู่

ตอนนี้สิ่งที่สนุกเริ่มต้นขึ้น: คุณจ้างคนทำอาหารเข้ามาในร้านอาหารของคุณซึ่งทำให้ความต้องการน้ำทั้งหมด 101 ซึ่งคุณไม่มี คุณต้องทำอะไรสักอย่าง

การจัดการน้ำ (= เคอร์เนล) มี 3 ตัวเลือก

1.ตัวเลือกแรกคือยกเลิกการเชื่อมต่อบริการสำหรับบ้านที่ไม่ได้ใช้น้ำเมื่อเร็ว ๆ นี้ นี่เป็นเรื่องปกติ แต่ถ้าบ้านที่ถูกตัดการเชื่อมต่อต้องการใช้น้ำอีกครั้งพวกเขาจะต้องผ่านกระบวนการลงทะเบียนที่มีความยาวอีกครั้ง การจัดการสามารถตัดการเชื่อมต่อบ้านหลายหลังเพื่อเพิ่มทรัพยากรน้ำให้มากขึ้น ที่จริงแล้วพวกเขาจะตัดการเชื่อมต่อทุกบ้านที่ไม่ได้ใช้น้ำเมื่อเร็ว ๆ นี้ดังนั้นจึงมีน้ำฟรีให้ใช้อยู่เสมอ

แม้ว่าเมืองของคุณจะยังคงใช้งานได้ข้อเสียคือความคืบหน้าจะหยุดชะงัก เวลาส่วนใหญ่ของคุณใช้เวลาในการรอการจัดการน้ำเพื่อคืนสถานะบริการของคุณ

นี่คือสิ่งที่เคอร์เนลทำกับเพจที่มีไฟล์สำรอง หากคุณเรียกใช้ไฟล์ปฏิบัติการขนาดใหญ่ (เช่น chrome) ไฟล์จะถูกคัดลอกหน่วยความจำ เมื่อหน่วยความจำเหลือน้อยหรือมีบางส่วนที่ไม่ได้เข้าถึงเมื่อเร็ว ๆ นี้เคอร์เนลจะสามารถดรอปส่วนเหล่านั้นได้เนื่องจากสามารถโหลดซ้ำจากดิสก์ได้ หากทำสิ่งนี้มากเกินไปสิ่งนี้จะทำให้เดสก์ท็อปของคุณหยุดทำงานเนื่องจากทุกอย่างจะรอดิสก์ IO โปรดทราบว่าเคอร์เนลจะลดลงอย่างมากเมื่อเร็ว ๆ นี้หน้าที่ใช้เมื่อคุณเริ่มทำ IO จำนวนมาก นี่คือเหตุผลที่ใช้เวลานานในการเปลี่ยนเป็นแอปพื้นหลังหลังจากที่คุณคัดลอกไฟล์ขนาดใหญ่หลาย ๆ ไฟล์เช่นภาพ DVD

นี่เป็นพฤติกรรมที่น่ารำคาญที่สุดสำหรับฉันเพราะฉันเกลียด hickups และคุณไม่สามารถควบคุมมันได้ มันเป็นการดีที่จะสามารถปิดได้ ฉันกำลังคิดถึงบางสิ่งตามแนวของ

sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c

จากนั้นคุณสามารถตั้งค่า vm_swappiness เป็น -1 เพื่อปิดการใช้งานนี้ สิ่งนี้ทำงานได้ค่อนข้างดีในการทดสอบเล็ก ๆ น้อย ๆ ของฉัน แต่ฉันไม่ได้เป็นนักพัฒนาเคอร์เนลดังนั้นฉันจึงไม่ได้ส่งให้ใคร

2ผู้บริหารสามารถปฏิเสธคำขอของแม่ครัวคนใหม่สำหรับน้ำได้ ตอนแรกฟังดูเหมือนความคิดที่ดี อย่างไรก็ตามมีข้อเสียอยู่สองประการ อย่างแรกคือมี บริษัท หลายแห่งที่ร้องขอการบอกรับสมาชิกจำนวนมากถึงแม้ว่าพวกเขาจะไม่ใช้ก็ตาม เหตุผลหนึ่งที่เป็นไปได้ในการทำเช่นนี้คือหลีกเลี่ยงค่าใช้จ่ายทั้งหมดในการพูดคุยกับการจัดการน้ำเมื่อใดก็ตามที่พวกเขาต้องการน้ำเพิ่ม ปริมาณการใช้น้ำของพวกเขาขึ้นและลงขึ้นอยู่กับเวลา เช่นในกรณีของร้านอาหาร บริษัท ต้องการน้ำมากขึ้นในช่วงเที่ยงเมื่อเทียบกับเที่ยงคืน ดังนั้นพวกเขาจึงร้องขอน้ำที่เป็นไปได้ทั้งหมดที่พวกเขาอาจใช้ แต่นั่นเป็นการสิ้นเปลืองน้ำในช่วงเที่ยงคืน ปัญหาคือทุก บริษัท ไม่สามารถคาดการณ์การใช้งานสูงสุดของพวกเขาได้อย่างถูกต้องดังนั้นพวกเขาจึงขอมากขึ้นโดยหวังว่าพวกเขาจะไม่ต้องกังวลเกี่ยวกับการร้องขอมากขึ้น

นี่คือสิ่งที่เครื่องเสมือนของ Java ทำ: มันจัดสรรหน่วยความจำจำนวนมากเมื่อเริ่มต้นและทำงานจากนั้น โดยค่าเริ่มต้นเคอร์เนลจะจัดสรรหน่วยความจำเฉพาะเมื่อแอป Java ของคุณเริ่มใช้งานจริง อย่างไรก็ตามหากคุณปิดใช้งาน overcommit เคอร์เนลจะทำการจองอย่างจริงจัง มันจะช่วยให้การจัดสรรจะประสบความสำเร็จถ้ามันมีทรัพยากรสำหรับมัน

อย่างไรก็ตามยังมีอีกปัญหาหนึ่งที่ร้ายแรงกว่าด้วยวิธีนี้ สมมติว่า บริษัท หนึ่งเริ่มขอน้ำหนึ่งหน่วยทุกวัน (มากกว่าในขั้นตอนที่ 10) ในที่สุดคุณจะไปถึงสถานะที่คุณมี 0 หน่วยฟรี ตอนนี้ บริษัท นี้จะไม่สามารถจัดสรรเพิ่มเติมได้ ไม่เป็นไรใครสนใจ บริษัท ใหญ่ ๆ แต่อย่างใด แต่ปัญหาคือบ้านเล็ก ๆ จะไม่สามารถขอน้ำเพิ่มได้อีก! คุณจะไม่สามารถสร้างห้องน้ำสาธารณะขนาดเล็กเพื่อรับมือกับการไหลเข้าของนักท่องเที่ยวอย่างฉับพลัน คุณจะไม่สามารถให้น้ำฉุกเฉินสำหรับไฟในป่าใกล้เคียง

ในแง่ของคอมพิวเตอร์: ในสถานการณ์ที่หน่วยความจำเหลือน้อยโดยไม่มีคำสั่งมากเกินไปคุณจะไม่สามารถเปิด xterm ใหม่คุณจะไม่สามารถ ssh เข้าไปในเครื่องของคุณคุณจะไม่สามารถเปิดแท็บใหม่เพื่อค้นหาสิ่งที่เป็นไปได้ แก้ไข กล่าวอีกนัยหนึ่งคือการปิดใช้งานการโอเวอร์เดตทำให้เดสก์ทอปของคุณไร้ประโยชน์เมื่อหน่วยความจำเหลือน้อย

3. ต่อไปนี้เป็นวิธีที่น่าสนใจในการจัดการปัญหาเมื่อ บริษัท เริ่มใช้น้ำมากเกินไป การจัดการน้ำพัดมันขึ้นมา! แท้จริง: มันไปที่เว็บไซต์ของร้านอาหารโยนระเบิดลงไปและรอจนกว่ามันจะระเบิด สิ่งนี้จะลดความต้องการน้ำของเมืองในทันทีโดยมากเพื่อให้ผู้คนใหม่ ๆ สามารถเข้ามาคุณสามารถสร้างห้องน้ำสาธารณะ ฯลฯ คุณในฐานะนายกเทศมนตรีสามารถสร้างร้านอาหารใหม่ได้ด้วยความหวังว่าคราวนี้จะต้องใช้น้ำน้อยลง ตัวอย่างเช่นคุณจะบอกให้คนอื่นไม่เข้าไปในร้านอาหารหากมีคนอยู่ภายในจำนวนมากเกินไป (เช่นคุณจะเปิดแท็บเบราว์เซอร์น้อยลง)

นี่คือสิ่งที่เคอร์เนลทำเมื่อไม่มีตัวเลือกทั้งหมดและต้องการหน่วยความจำ: มันเรียก OOM killer มันเลือกแอปพลิเคชั่นขนาดใหญ่ (ขึ้นอยู่กับฮิวริสติกจำนวนมาก) และฆ่ามันปล่อยหน่วยความจำจำนวนมาก แต่ยังคงเดสก์ท็อปที่ตอบสนองได้ อันที่จริงแล้วเคอร์เนล Android ทำสิ่งนี้อย่างจริงจังยิ่งขึ้น: มันฆ่าแอปที่ใช้งานน้อยที่สุดเมื่อหน่วยความจำเหลือน้อย (เมื่อเทียบกับเคอร์เนลหุ้นซึ่งทำหน้าที่เป็นทางเลือกสุดท้ายเท่านั้น) สิ่งนี้เรียกว่า Viking Killer ใน Android

ฉันคิดว่านี่เป็นหนึ่งในวิธีแก้ปัญหาที่ง่ายที่สุด: ไม่ใช่ว่าคุณมีตัวเลือกมากกว่านี้ดังนั้นทำไมไม่รีบไปเร็วกว่านี้ใช่ไหม? ปัญหาคือเคอร์เนลบางครั้งทำงานค่อนข้างมากเพื่อหลีกเลี่ยงการเรียก OOM killer นั่นเป็นสาเหตุที่คุณเห็นว่าเดสก์ท็อปของคุณช้ามากและเคอร์เนลไม่ได้ทำอะไรเกี่ยวกับเรื่องนี้ แต่โชคดีที่มีตัวเลือกในการเรียก OOM killer ด้วยตัวคุณเอง! ก่อนอื่นตรวจสอบให้แน่ใจว่าได้เปิดใช้งานคีย์ Magic sysrq (เช่นecho 1 | sudo tee /proc/sys/kernel/sysrq) ทุกครั้งที่คุณรู้สึกว่าเคอร์เนลมีหน่วยความจำเหลือน้อยเพียงกด Alt + SysRQ, Alt + f

ตกลงดังนั้นทั้งหมดที่ดี แต่คุณต้องการที่จะลอง? สถานการณ์หน่วยความจำต่ำนั้นง่ายมากในการทำซ้ำ ฉันมีแอพที่ง่ายมากสำหรับสิ่งนั้น คุณจะต้องเรียกใช้สองครั้ง การรันครั้งแรกจะกำหนดว่าคุณมี RAM ว่างเท่าใดการรันครั้งที่สองจะสร้างสถานการณ์หน่วยความจำเหลือน้อย โปรดทราบว่าวิธีนี้ถือว่าคุณปิดใช้งานการสลับ (เช่นทำsudo swapoff -a) รหัสและการใช้งานมีดังนี้:

// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    int limit = 123456789;
    if (argc >= 2) {
        limit = atoi(argv[1]);
    }
    setbuf(stdout, NULL);
    for (int i = 1; i <= limit; i++) {
        memset(malloc(1 << 20), 1, 1 << 20);
        printf("\rAllocated %5d MiB.", i);
    }
    sleep(10000);
    return 0;
}

และนี่คือวิธีที่คุณใช้:

$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed

การเรียกครั้งแรกตรวจพบว่าเรามี RAM 31,118 MiB ฟรี ดังนั้นฉันจึงบอกให้แอปพลิเคชั่นจัดสรร 31,110 MiB RAM เพื่อที่เคอร์เนลจะไม่ฆ่า แต่กินหน่วยความจำเกือบทั้งหมด ระบบของฉันค้าง: แม้แต่ตัวชี้เมาส์ก็ไม่ขยับเขยื่อน ฉันกด Alt + SysRQ, Alt + f และมันฆ่ากระบวนการ eatmem ของฉันและระบบได้รับการกู้คืน

แม้ว่าเราจะครอบคลุมตัวเลือกของเราสิ่งที่ทำในสถานการณ์ความจำต่ำวิธีที่ดีที่สุด (เช่นเดียวกับสถานการณ์อันตรายอื่น ๆ ) คือการหลีกเลี่ยงในครั้งแรก มีหลายวิธีในการทำเช่นนี้ วิธีการทั่วไปที่ฉันเห็นคือการนำแอปพลิเคชั่นที่ทำงานผิดปกติ (เช่นเบราว์เซอร์) ลงในคอนเทนเนอร์ที่แตกต่างจากส่วนที่เหลือของระบบ ในกรณีนี้เบราว์เซอร์จะไม่สามารถส่งผลกระทบต่อเดสก์ท็อปของคุณ แต่การป้องกันตัวเองอยู่นอกขอบเขตของคำถามดังนั้นฉันจะไม่เขียนเกี่ยวกับมัน

TL; DR:แม้ว่าในขณะนี้ไม่มีวิธีที่จะหลีกเลี่ยงการเพจได้อย่างสมบูรณ์ แต่คุณสามารถลดการหยุดทำงานของระบบได้อย่างสมบูรณ์โดยการปิดใช้งานคำสั่งเกินคำสั่ง แต่ระบบของคุณจะยังไม่สามารถใช้งานได้ในช่วงที่มีหน่วยความจำเหลือน้อย แต่จะแตกต่างกัน ในสถานการณ์ที่มีหน่วยความจำต่ำให้กด Alt + SysRQ, Alt + f เพื่อฆ่ากระบวนการขนาดใหญ่ของการเลือกเคอร์เนล ระบบของคุณควรกู้คืนการตอบสนองภายในไม่กี่วินาที นี่ถือว่าคุณเปิดใช้งานคีย์ sysrq (โดยค่าเริ่มต้น)


ฉันให้คุณทุกชื่อเสียงของฉันเป็นความโปรดปรานในทรัพยากรนี้ดังนั้นฉันไม่สามารถแม้แต่แสดงความคิดเห็น :) ในที่สุดฉันได้รับบางส่วนที่จะพูดขอบคุณสำหรับคำตอบที่ดีนี้! ฉันกำลังจัดการกับปัญหานี้ตลอดเวลาที่ฉันมีแล็ปท็อปของฉันที่มี 8GB (บ้า แต่ระบบของฉันจะออกจากหน่วยความจำอย่างสม่ำเสมอวันนั้น) เมื่อเร็ว ๆ นี้ฉันพบโครงการนี้: github.com/rfjakob/earlyoomซึ่งอาจช่วยป้องกันระบบที่หยุดทำงานด้วยการฆ่ากระบวนการบางอย่างก่อนที่มันจะสายเกินไป
Vlad Frolov

4

การวางไฟล์ชั่วคราวและไฟล์แคชทั้งหมดของคุณลงบน a tmpfsกำลังลดจำนวน RAM ว่างที่คุณมีอยู่ดังนั้นคุณอาจทำให้ระบบเปลี่ยนไปเร็วกว่าที่ควรจะเป็นหากไม่มีสิ่งนี้

ดูเหมือนว่าคุณมีแอปพลิเคชั่นบางตัวที่ใช้เคอร์เนลหรือไดรเวอร์บางตัวที่กำลังโหลดมากเกินไป คุณไม่ได้ลงรายละเอียดมากเกินไปเกี่ยวกับประเภทของแอปพลิเคชันอื่น ๆ ที่นอกเหนือจากที่คุณใช้เบราว์เซอร์และตัวจัดทำดัชนีและคุณได้ปิดการใช้งานตัวจัดทำดัชนี

คุณอาจลองเปลี่ยนไปใช้สภาพแวดล้อมแบบเดสก์ท็อปหรือตัวจัดการหน้าต่างที่ใช้ทรัพยากรน้อยลงเช่น LXDE หรือ IceWM ที่ทำงานฉันใช้ระบบ Linux ที่ติดตั้ง LXDE และ ROX-Filer สำหรับสภาพแวดล้อมเดสก์ท็อปน้อยที่สุด จุดประสงค์ของระบบ Linux นี้คือการเรียกใช้ VMWare Player เพื่อให้ฉันสามารถเรียกใช้ Windows XP และ Windows 7 ได้พร้อมกัน มันเป็นรายละเอียดฮาร์ดแวร์ที่คล้ายกับสิ่งที่คุณพูดและฉันไม่ได้มีปัญหาการตอบสนองมากเกินไปภายใต้ภาระหนักนี้ฉันกำลังใส่ฮาร์ดแวร์ผ่าน ฉันไม่ได้มีปัญหาการตอบสนองใด ๆกับ Linux (โดยปกติจะเป็น VM ที่บางครั้งทำให้ฉันรอสักครู่และแชร์ดิสก์ 1 แผ่นระหว่าง 2 VMs + 1 OS อย่างที่คาดไว้) และสามารถระงับหรือปิด VM ได้ทุกเมื่อ ฉันต้องการ

ดังนั้นสำหรับฉันมันชี้ให้เห็นถึงปัญหาบางอย่างกับแอปพลิเคชันเฉพาะที่คุณใช้งานอยู่

DMA เปิดใช้งานสำหรับดิสก์ไดรฟ์ของคุณหรือไม่ (ใช้hdparm) หากคุณใช้การเข้ารหัสดิสก์เต็มรูปแบบนั้นต้องใช้การรับส่งข้อมูลดิสก์ทั้งหมดผ่าน CPU ซึ่งทำให้ DMA ได้รับประโยชน์มากมาย ผลของสิ่งนั้นก็คือปริมาณการใช้งานดิสก์ที่สูงนั้นทำให้ซีพียูมีความเร็วสูงซึ่งจะทำให้ระบบทั้งหมดช้าลง (แก้ไข: เพื่อให้ความกระจ่างว่าการปิดใช้งานหรือใช้ DMA dm-cryptจะทำให้ CPU สูงในระหว่างการรับส่งข้อมูลดิสก์สูง)


2
ประเด็นของคำถามไม่ใช่ว่า WM นั้นมีป่องและทำให้ระบบช้า (น่าจะตอบสนองได้อย่างสมบูรณ์แบบในการใช้งานปกติ) แต่เคอร์เนลไม่ได้จัดลำดับความสำคัญของแอปพลิเคชันอย่างเหมาะสมเมื่อหน่วยความจำหมดและต้องเข้าไป การแลกเปลี่ยนอย่างหนัก ฉันเคยมีปัญหานี้บนเดสก์ท็อปทุกเครื่องที่ฉันเคยใช้มาและในขณะที่ใช้โปรแกรมที่เบากว่าหรือเพิ่ม RAM เพิ่มเติมอาจช่วยได้ แต่ก็ไม่ได้จัดการกับปัญหา
crazy2be

ในโพสต์ก่อนหน้าของฉันฉันได้กล่าวต่อไปนี้: "ดูเหมือนว่าคุณมีแอปพลิเคชั่นบางตัวที่ใช้เคอร์เนลหรือไดร์เวอร์บางตัว ดังนั้นคอขวดอาจอยู่ในเคอร์เนลโมดูลที่เฉพาะเจาะจง ฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับเคอร์เนล แต่ฉันแน่ใจว่าการจัดสรรหน่วยความจำจากด้านเคอร์เนลโดยเฉพาะด้านโมดูลทำงานแตกต่างจากฝั่งผู้ใช้ การใช้งาน CPU ในเคอร์เนลก็มีการจัดการที่แตกต่างกัน (ไม่ทราบว่าคุณสามารถประมวลผลเคอร์เนล "ดี") ฉันไม่สามารถแสดงความคิดเห็นเพิ่มเติมโดยไม่ทราบว่ามีแอปพลิเคชันเฉพาะที่เกี่ยวข้อง
LawrenceC

นอกจากนี้หากคุณกำลังใช้ FUSE NTFS ที่อาจทำให้เกิดความช้า
LawrenceC

1
ฉันทราบว่าระบบไฟล์ที่ใช้ RAM เช่น tmpfs (ชัด) ทำให้ RAM หมดเร็วกว่าและ WM ที่มีน้ำหนักเบาสามารถลดอาการของปัญหาพื้นฐานได้เล็กน้อย ฉันรู้สึกกดดันที่จะใช้ tmpfs เนื่องจากการตอบสนองต่อการเขียนลงดิสก์ไม่ดีอาจทำให้เกิด อย่างไรก็ตามขอขอบคุณสำหรับคำแนะนำของคุณโดยเฉพาะอย่างยิ่งส่วนที่เกี่ยวกับ DMA ซึ่งฉันได้เพิ่มไว้ในรายการหัวข้อที่เกี่ยวข้อง สำหรับบันทึกฉันเชื่อว่า DMA เปิดใช้งานอยู่และฉันไม่ได้ใช้ระบบไฟล์เข้ารหัส
user76871

1

นี่เป็นปัญหาทั่วไปของตัวกำหนดตารางเวลาของ Linux ระบบช้าลงเป็นการรวบรวมข้อมูลทุกครั้งที่มีการทำกิจกรรมหนัก ๆ ของ IO มีหลายสิ่งที่คุณสามารถทำได้เพื่อปรับปรุงสถานการณ์ยกเว้นว่าคุณกำลังเข้าสู่การแฮ็คเคอร์เนล :)

บางทีสิ่งเหล่านี้สามารถช่วย:

http://www.phoronix.com/scan.php?page=article&item=linux_2637_video&num=1

http://www.osnews.com/story/24223/Alternative_to_the_200_Lines_Kernel_Patch_that_Does_Wonders_


1
ดังที่ฉันจำได้ว่าแพทช์เคอร์เนลเหล่านี้มีความเกี่ยวข้องเฉพาะในกรณีที่คุณคอมไพล์โปรแกรมหรือทำอย่างอื่นที่มี CPU (และ IO) หนักมากในเทอร์มินัลในขณะที่พยายามโต้ตอบกับแอปพลิเคชัน GUI มันไม่ได้ช่วยในสถานการณ์ที่พบบ่อยมากขึ้นที่แอปพลิเคชัน GUI หนึ่งทำงานหนักและคุณพยายามทำงานกับแอปพลิเคชั่น GUI อื่นขออภัย
crazy2be

0

แม้ว่าคำถามจะมีอายุมากกว่าสองปีและคำตอบของ @ ypsu นั้นยอดเยี่ยม แต่สถานการณ์ของระบบที่ใช้ระบบปฏิบัติการ Linux นั้นไม่ดีเนื่องจากการขาด RAM ยังคงอยู่ที่นี่

นี่คือการสังเกตของฉันเกี่ยวกับปัญหา: แม้ว่าฉันจะไม่มี swap เลยเมื่อระบบขาดหน่วยความจำตัวบ่งชี้ฮาร์ดไดรฟ์ของฉันก็จะสว่างขึ้นเพราะโหลดดิสก์ได้ 100% จากข้อเท็จจริงนี้ดูเหมือนว่าสาเหตุที่แท้จริงคือเคอร์เนลพยายามที่จะเพิ่มหน่วยความจำโดยการยกเลิกการโหลดบางสิ่งที่สามารถกู้คืนได้จากดิสก์และแน่นอนที่สุดคือไลบรารีที่ใช้ร่วมกัน เนื่องจากแอปพลิเคชัน GUI มักมีไลบรารีที่ใช้ร่วมกันจำนวนมากดูเหมือนว่าระบบอาจคิดว่ามันเพียงพอที่จะยกเลิกการโหลดบางส่วนเท่านั้น แต่จะทำงานได้จนถึงการดำเนินการพื้นที่ผู้ใช้ถัดไปซึ่งต้องใช้ไลบรารีที่ไม่โหลดเหล่านั้น นี่น่าจะเป็นสถานการณ์ที่เป็นไปได้มากที่สุดที่ทำให้เกิดการวนซ้ำของการไม่โหลดไลบรารีที่ใช้ร่วมกันและโหลดมันกลับมา

มีโครงการที่ทำหน้าที่เป็นภูตพื้นที่ผู้ใช้ที่ฆ่ากระบวนการหิวมากที่สุดของหน่วยความจำก่อนที่มันจะสายเกินไป: https://github.com/rfjakob/earlyoom

นอกจากนี้ฉันเคยใช้คอนเทนเนอร์ Docker ที่มีขีด จำกัด หน่วยความจำที่มีสติสำหรับแอปพลิเคชันที่ใช้หน่วยความจำ (เช่น Chrome)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.