วิธีแก้ปัญหาความจำนี้อย่างสง่างาม?


10

ฉันมีแล็ปท็อปมาตรฐาน Linux (ทดสอบเดเบียน) ที่มีพาร์ทิชันสลับ

ฉันทำการทดลองกับมันมากมาย บางส่วนของพวกเขากำลังหิวมากหน่วยความจำและวิธีการทำงานของ Linux โดยค่าเริ่มต้นเป็นปัญหาสำหรับฉัน ... ขอยกตัวอย่างโง่ ๆ :

  1. นั่งหน้าแล็ปท็อป
  2. เปิดเทอร์มินัล
  3. พิมพ์pythonจากนั้นa = [0]*100000000

ตอนนี้มีโอกาสสูงที่คุณจะมี RAM ไม่เพียงพอที่จะจัดการกับรายการใหญ่ Linux จะเติม RAM แล้วสลับและอีกสองสามนาทีต่อมา OOM killer จะถูกทริกเกอร์และฆ่าบริการแบบสุ่ม (เกือบ) และหวังว่าถ้าคุณกด Ctrl + C ในเวลาที่เหมาะสมpythonและถ้าเทอร์มินัล ยังคงมีสมาธิคอมพิวเตอร์จะตอบสนองอีกครั้ง

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

ulimit -Sv [mem] ฉันได้ยินที่ด้านหลัง!

โฮ้โฮ! "ใช้งานcgroupsผ่านcgexec!" บางคนบอกว่าแถวแรก!

ใช่คุณพูดถูก: นี่เป็นคำตอบที่ดีมาก แต่:

  • ไม่ใช้ทั้งระบบ
  • มีการกำหนดขีด จำกัด ต่อกระบวนการ
  • ข้อ จำกัด คงที่โดยไม่คำนึงถึงจำนวนจริงของ RAM ว่าง (AFAIK)
  • ที่นี่และมีพวกเขากล่าวว่าเหล่านี้ไม่ได้จริงๆเป็นทางออกที่ดีในการบังคับใช้ข้อ จำกัด อย่างหนัก

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

หรือ: "คุณกำลังทำอะไรอยู่คุณต้องการx MB และมีเฉพาะy MB เท่านั้นใช่ SWAP ว่างเปล่า แต่คุณไม่ต้องการใช้ SWAP เพื่อทำงานสกปรกคุณใช่ไหมฉันไม่ ไม่ว่าไม่มีความทรงจำสำหรับคุณ! ถ้าคุณยืนยันคุณจะต้องตาย! "


2
มีอัลกอริทึมที่อธิบายไว้ในบทความนี้แล้วซึ่งจะช่วยให้นักฆ่า OOM เลือกกระบวนการที่ถูกต้อง การเปลี่ยนแปลง/proc/sys/vm/overcommit_memoryส่งผลกระทบต่อพฤติกรรมของเคอร์เนลในหน่วยความจำเหลือน้อย
jofel

1
ใช่ แต่overcommit_memoryไฟล์พิเศษใช้ RAM + SWAP เป็นหน่วยความจำที่ใช้งานได้ ฉันยังคงแลกเปลี่ยน :)

1
คุณต้องอธิบายว่าสิ่งนี้ไม่ใช่ของซ้ำกันอย่างไร : unix.stackexchange.com/questions/34334/…ซึ่งขัดแย้งกับคุณ WRT cgroups และผู้ใช้รายบุคคล PS หากคุณไม่ต้องการที่จะแลกเปลี่ยนปิดการใช้งานแลกเปลี่ยน
goldilocks

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

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

คำตอบ:


4

cgroupsมีคนแนะนำในการได้ยินของคุณ พยายามค้นหาทิศทางนั้นให้ดี:

  • นำไปใช้กับกลุ่มงานที่คุณเลือก (ไม่ใช่ระบบทั่ว แต่ไม่ใช่ต่อกระบวนการ)
  • มีการกำหนดขีด จำกัด สำหรับกลุ่ม
  • ข้อ จำกัด คงที่
  • พวกเขาสามารถบังคับใช้ขีด จำกัด ฮาร์ดในหน่วยความจำและ / หรือหน่วยความจำ + สลับ

บางอย่างเช่นนั้นอาจนำคุณเข้าใกล้เป้าหมาย :

group limited {
  memory {
    memory.limit_in_bytes = 50M;
    memory.memsw.limit_in_bytes = 50M;
  }
}

สิ่งนี้บอกว่างานภายใต้ cgroup นี้สามารถใช้งานได้สูงสุด 50M ของหน่วยความจำเท่านั้นและ 50M ของหน่วยความจำ + swap ดังนั้นเมื่อหน่วยความจำเต็มจะไม่ทำการสลับ แต่ถ้าหน่วยความจำไม่เต็มและข้อมูลบางส่วนอาจถูกแมป สลับนี้อาจได้รับอนุญาต

นี่คือข้อความที่ตัดตอนมาจากเอกสารหน่วยความจำของ cgroup :

โดยใช้ขีด จำกัด memsw คุณสามารถหลีกเลี่ยงระบบ OOM ซึ่งอาจเกิดจากการขาดแคลน swap


ยังไม่ตรงกับที่ฉันคาดหวัง แต่ความแตกต่างระหว่างสิ่งที่ฉันคาดหวังและความจริงมักจะมีขนาดใหญ่มาก :) ในกรณีนี้ฉันต้องการให้แน่ใจว่าฉันไม่ได้พลาดอะไรเช่นovercommit_memoryตัวแปรเคอร์เนล ขอบคุณทุกคน.

0

ฉันพบปัญหาเดียวกันบ่อยครั้ง เวิร์กโฟลว์ทั่วไปของฉันเกี่ยวข้องกับการคำนวณจำนวนมากใน MATLAB บางครั้งฉันจะพยายามจัดสรรตัวแปรใหม่ที่เกินจำนวนหน่วยความจำที่มีอยู่โดยไม่ตั้งใจ ระบบหยุดทำงานและโดยทั่วไปฉันต้องรีบูตเครื่องเพื่อกลับมาทำงานอีกครั้ง : P

ในกรณีของฉันและดูเหมือนว่าในตัวคุณฉันก็ไม่ได้กังวลอะไรมากกับการ จำกัด จำนวนหน่วยความจำ MATLAB ที่ใช้เป็นจำนวนคงที่ - ฉันสนใจที่จะไม่มีเครื่องแช่แข็งและฉันยินดีที่จะเสียสละกระบวนการ MATLAB ของฉัน เพื่อรักษาการตอบสนองของระบบ

แรงบันดาลใจจากการตอบกลับโพสต์นี้ฉันเขียนสคริปต์ต่อไปนี้ (ฉันเรียกมันว่า watch_memory.sh):

#!/bin/bash

MONITOR=$(free | grep 'buffers/cache:')
MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')

MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))

while :; do
    if [ "$MEM_PERC" -gt "95" ]
    then
        kill $1
        echo "$1 killed for using too much memory."
        exit
    fi
    sleep 1

    MONITOR=$(free | grep 'buffers/cache:')
    MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
    MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')
    MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))
done

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

หากไม่มีการปรับระดับความสำคัญ (ความดี) ของสคริปต์ใช้เวลาประมาณ 10-20 วินาทีเพื่อให้แพะรับบาปถูกฆ่า แต่มันก็ยังใช้ได้ การเรียกใช้สคริปต์ที่มีลำดับความสำคัญเป็นลบนั้นส่งผลให้เกิดการฆ่าทันทีหลังจากการละเมิด (11916 ในตัวอย่างนี้คือ pid ที่ฉันต้องการฆ่าหากหน่วยความจำไม่เพียงพอ):

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