ฉันจะ จำกัด จำนวนหน่วยความจำที่ใช้ได้กับกระบวนการได้อย่างไร


11

ฉันกำลังพัฒนาโปรแกรมที่กำลังดำเนินอยู่ บางครั้งมันก็สิ้นสุดการจัดสรรหน่วยความจำจำนวนมาก (>> 10G บนเครื่องที่มีหน่วยความจำกายภาพ 8G) ทำให้ระบบไม่ตอบสนอง ฉันต้องการ จำกัด จำนวนหน่วยความจำที่กระบวนการสามารถจัดสรรได้ วิธีปกติที่ฉันจะทำคือ:

ulimit -m 4000000 ; ./myprogram

... ซึ่งควรฆ่าโปรแกรมของฉันหากพยายามใช้หน่วยความจำมากกว่า 4GB

ใน OS X El Capitan สิ่งนี้ดูเหมือนว่าจะไม่มีผลกระทบ แม้ulimit -m 1(จำกัด โปรแกรมทั้งหมดให้เหลือเพียง 1kB ของหน่วยความจำ!) ก็ไม่มีประสิทธิภาพ

ฉันจะตั้งค่าขอบเขตบนของหน่วยความจำที่พร้อมใช้งานสำหรับกระบวนการเฉพาะได้อย่างไร


เมื่อคุณพูดตามปกติฉันจะทำสิ่งนี้คุณหมายถึงอะไร โดยเฉพาะอย่างยิ่งเมื่อใดที่คุณมักจะทำเช่นนี้? และเมื่อคุณทำเช่นนั้นคุณหมายถึงภายใน Mac OS X El Capitan หรือในสภาพแวดล้อมอื่นหรือไม่? คุณสามารถยกตัวอย่างเมื่อคุณใช้สำเร็จหรือไม่? โดยทั่วไปฉันแค่พยายามชี้แจงว่ากระบวนการนี้เหมาะกับคุณตามปกติหรือไม่ แต่ใช้ไม่ได้กับโปรแกรมเฉพาะนี้ หรือมันไม่ได้ผลสำหรับคุณ แต่คุณคิดว่ามันควรจะเป็นอย่างไร
Monomeeth

1
โดย "วิธีปกติที่ฉันจะทำ" ฉันหมายถึงวิธีที่ฉันจะทำสิ่งนี้กับรสชาติอื่น ๆ ของยูนิกซ์ ฉันทราบว่าฉันเพิ่งค้นพบว่าulimit -mไม่สามารถใช้งานบน Linux ได้อีกต่อไป (> 2.4.30) แต่ulimit -vก็ยังทำงานได้ตามที่คาดไว้ (เช่นulimit -mนั้นulimit -vดูเหมือนว่าจะไม่มีผลกับ OS X ด้วย)
cpcallen

ฟังดูเหมือนว่าคุณมีหน่วยความจำรั่วในโปรแกรมที่คุณกำลังเขียนและจำเป็นต้องทำการเก็บขยะที่ดีขึ้น คุณอ่านข้อมูลเกี่ยวกับการจัดการหน่วยความจำแล้วหรือยัง?
ทอดด์ Dabney

1
ไม่ไม่ใช่การรั่วไหลของหน่วยความจำ - เพียงแค่ค้นหากราฟของพื้นที่รัฐที่มีขนาดใหญ่มาก ฉันสามารถเพิ่มรหัสเพื่อยกเลิกการค้นหาหากโครงสร้างภายในต่างๆมีขนาดใหญ่เกินไป แต่ฉันคาดว่าจะสามารถทำสิ่งเดียวกันได้ (ป้องกันเครื่องไม่ให้รับข้อมูลจากอินพุตขนาดใหญ่) ด้วย shell one-liner
cpcallen

คำตอบ:


1

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

หากคุณยืนยันในแนวทางการโพสต์ในอดีตคุณสามารถใช้สคริปต์ Bash ต่อไปนี้ สคริปต์นี้จะค้นหาจำนวนหน่วยความจำ (ตามที่กำหนดโดย "ขนาดชุดที่อยู่อาศัย") ขั้นตอนที่ใช้กับ processid pid กรองข้อมูลที่ไม่ใช่ตัวเลขทั้งหมดโดยใช้ grep และบันทึกจำนวนเป็นตัวแปร n สคริปต์จะตรวจสอบว่า n มากกว่า x ที่คุณระบุหรือไม่ หากเป็นเช่นนั้นกระบวนการที่มี processid pid จะถูกฆ่า

โปรดทราบ:

  1. คุณต้องแทนที่<pid>ด้วยรหัสกระบวนการของโปรแกรมของคุณ
  2. คุณต้องแทนที่<x>ด้วย rss = "ขนาดชุดที่อยู่อาศัย" (เช่นขนาดหน่วยความจำจริง) ที่คุณไม่ต้องการให้โปรแกรมเกินขนาด

n=$(ps -<pid> -o rss | grep '[0-9]') if [ $n -gt <x> ]; then kill -9 <pid>; fi

หากคุณต้องการให้สิ่งนี้ทำงานทุก ๆ y วินาทีให้ปิดไว้ในลูปและบอกให้รอ y วินาทีหลังจากการวนซ้ำทุกครั้ง topนอกจากนี้คุณยังสามารถเขียนคำสั่งที่คล้ายกันโดยใช้ จุดเริ่มต้นของคุณtop -l 1|grep "<pid>"|awk '{print $10}'คือ

คำตอบของ @ kenorb ช่วยฉันด้วยสคริปต์ของฉัน


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

ประการแรกคุณแน่ใจหรือว่าการใช้หน่วยความจำนั้นเป็นปัญหาจริงๆ สถานะเอกสารประกอบของ Go :

ตัวจัดสรรหน่วยความจำตัว Go จะสงวนพื้นที่ส่วนใหญ่ของหน่วยความจำเสมือนไว้เป็นเวทีสำหรับการจัดสรร หน่วยความจำเสมือนนี้เป็นของท้องถิ่นสำหรับกระบวนการ Go ที่เฉพาะเจาะจง การจองไม่ได้กีดกันกระบวนการความจำอื่น ๆ

หากคุณยังคิดว่าคุณมีปัญหาฉันขอแนะนำให้คุณจัดการหน่วยความจำของคุณด้วยตนเองตามที่เขียนไว้ในภาษา C เนื่องจาก go ถูกเขียนใน C ฉันสงสัยว่าจะมีวิธีในการจัดการหน่วยความจำ / การจัดสรร C และมีแน่นอน ดูที่เก็บgithubนี้ซึ่ง

ช่วยให้คุณจัดการหน่วยความจำด้วยตนเองผ่านตัวจัดสรร C มาตรฐานสำหรับระบบของคุณ มันเป็นเสื้อคลุมบาง ๆ ด้านบนของ malloc, calloc และเป็นอิสระจาก ดู man malloc สำหรับรายละเอียดเกี่ยวกับฟังก์ชั่นเหล่านี้สำหรับระบบของคุณ ไลบรารีนี้ใช้ cgo

กรณีการใช้งานจะได้รับเป็น:

ทำไมคุณต้องการสิ่งนี้

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

ดูเหมือนว่าจะเป็นทางออกระยะยาวที่ดีกว่า

หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ C (รวมถึงการจัดการหน่วยความจำ) ภาษา C การเขียนโปรแกรมเป็นการอ้างอิงมาตรฐาน


ฉันแน่ใจว่าการใช้หน่วยความจำเป็นปัญหาจริงๆ เมื่อโปรแกรมเพิ่มขนาดหน่วยความจำกายภาพ> 2x โดยไม่คาดคิดเครื่องเกือบจะไม่ตอบสนองทั้งหมดเนื่องจากหน้าฟาด ใช้เวลาประมาณหนึ่งชั่วโมงเมื่อฉันกด ^ C และเมื่อ macOS กลับมาทำงานต่อเมื่อคลิกเมาส์ ในเวลานั้นมีหลักฐานเพียงหลักฐานเดียวที่บ่งบอกว่ามันไม่แข็งตัวคือเสียงเงียบของฮาร์ดไดรฟ์ที่กำลังเกิดขึ้นอย่างรวดเร็ว
cpcallen

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

@cpcallen ทำการค้นหาบางอย่างดูเหมือนว่า "พารามิเตอร์ -m เพื่อ ulimit ไม่มีผลกับระบบ Linux ที่มีเคอร์เนลเวอร์ชันล่าสุดกว่า 2.4.30" ดูเหมือนว่า OSX จะมีการเปลี่ยนแปลงนี้ด้วย ลองใช้ตัวเลือก -v เพื่อ จำกัด พื้นที่ที่อยู่
Evan Rosica

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