วิธีการเติม 90% ของหน่วยความจำฟรี


181

ฉันต้องการทำการทดสอบที่มีทรัพยากรต่ำและฉันจำเป็นต้องมีหน่วยความจำว่าง 90% ที่เต็ม

ฉันจะทำสิ่งนี้บน*nixระบบได้อย่างไร?


3
มันจริงๆต้องทำงานในใด ๆ * ระบบระวัง?
CVn

31
คุณสามารถสร้าง VM (โดยใช้นักเทียบท่าหรือคนเร่ร่อนหรือสิ่งอื่นที่คล้ายคลึงกัน) ที่มีหน่วยความจำในจำนวนที่ จำกัด หรือไม่?
abendigo

4
@abendigo สำหรับ QA โซลูชันที่นำเสนอในที่นี้มีประโยชน์มากมาย: สำหรับระบบปฏิบัติการทั่วไปที่ไม่มีแพลตฟอร์มเฉพาะพารามิเตอร์ VM หรือเคอร์เนลสำหรับบูตอาจมีประโยชน์ แต่สำหรับระบบฝังตัวที่คุณทราบข้อกำหนดหน่วยความจำของระบบเป้าหมายที่ฉันต้องการ ไปเพื่อเติมหน่วยความจำฟรี
Eduard Florinescu

2
ในกรณีที่คนอื่นตกใจเล็กน้อยจากการให้คะแนนที่นี่: meta.unix.stackexchange.com/questions/1513/… ?
goldilocks

ดูเพิ่มเติมที่: unix.stackexchange.com/a/1368/52956
Wilf

คำตอบ:


156

stress-ngเป็นตัวสร้างเวิร์กโหลดที่จำลอง cpu / mem / io / hdd stress บนระบบ POSIX การโทรนี้ควรทำเคล็ดลับบน Linux <3.14:

stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

สำหรับ Linux> = 3.14 คุณสามารถใช้MemAvailableแทนการประมาณหน่วยความจำที่มีอยู่สำหรับกระบวนการใหม่โดยไม่ต้องสลับ:

stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

ปรับ/proc/meminfoสายด้วยfree(1)/ vm_stat(1)/ ฯลฯ หากคุณต้องการพกพา


3
ความเครียด --vm-bytes $ (awk '/ MemFree / {printf "% d \ n", $ 2 * 0.097;}' </ proc / meminfo) k --vm-keep -m 10
Robert

1
MemFree ส่วนใหญ่ถูกเก็บไว้โดยระบบปฏิบัติการดังนั้นฉันจึงใช้ MemAvailable แทน สิ่งนี้ทำให้ฉันมีการใช้งาน 92% ใน Cent OS 7stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
kujiy

เป็นการดีที่จะทราบว่า MemAvailable ถูกเพิ่มเข้าไปใน "การประเมินจำนวนหน่วยความจำที่พร้อมใช้งานสำหรับการเริ่มต้นแอปพลิเคชันใหม่โดยไม่ต้องสลับ" ดูgit.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/ …และgit.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/…
tkrennwa

1
เช่นเดียวกับบันทึกเสริมการให้บริการทั้งสอง--vm 1 and --vm-keepมีความสำคัญ เพียงแค่--vm-bytesไม่ทำอะไรเลยและคุณอาจจะหลงคิดว่าคุณสามารถจัดสรรหน่วยความจำมากที่สุดเท่าที่คุณต้องการ / ความต้องการของคุณ ฉันได้รับบิตนี้จนกว่าฉันจะพยายามตรวจสอบตัวเองด้วยการจัดสรรหน่วยความจำ 256G นี่ไม่ใช่ข้อบกพร่องในคำตอบมันให้ค่าสถานะที่ถูกต้องเพียงแค่ระมัดระวังเพิ่มเติม
ffledgling

-m 1นี่คือเหตุผลที่มี ตาม manpage ความเครียด-m Nสั้นสำหรับ--vm N: วางไข่Nคนงานปั่นบนmalloc()/free()
tkrennwa

92

คุณสามารถเขียนโปรแกรม C ไปmalloc()ยังหน่วยความจำที่ต้องการจากนั้นใช้mlock()เพื่อป้องกันไม่ให้หน่วยความจำถูกสลับ

จากนั้นให้โปรแกรมรออินพุตคีย์บอร์ดและปลดล็อกหน่วยความจำเพิ่มหน่วยความจำและออก


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

2
ฉันเห็นด้วยกับ @siri; อย่างไรก็ตามขึ้นอยู่กับตัวแปร UNIX ที่คุณใช้
Anthony

2
แรงบันดาลใจบางอย่างสำหรับรหัส นอกจากนี้ผมคิดว่าคุณไม่จำเป็นที่จะปลดล็อค / ฟรีหน่วยความจำ ระบบปฏิบัติการจะทำเพื่อคุณเมื่อกระบวนการของคุณสิ้นสุดลง
เซบาสเตียน

9
คุณอาจต้องเขียนไปยังหน่วยความจำจริง ๆ แล้วเคอร์เนลอาจ overcommit ถ้าคุณ malloc เท่านั้น หากกำหนดค่าเช่น Linux จะอนุญาตให้ malloc ส่งคืนได้สำเร็จโดยไม่ต้องมีหน่วยความจำว่างจริง ๆ และจะจัดสรรหน่วยความจำเมื่อเขียนไปเท่านั้น ดูwin.tue.nl/~aeb/linux/lk/lk-9.html
Bjarke Freund-Hansen

7
@Sebastian: callocจะพบปัญหาเดียวกัน IIRC หน่วยความจำทั้งหมดจะชี้ไปที่หน้าศูนย์อ่านอย่างเดียวที่เหมือนกัน มันจะไม่ได้รับการจัดสรรจนกว่าคุณจะพยายามเขียนลงไป (ซึ่งจะไม่ทำงานเนื่องจากเป็นแบบอ่านอย่างเดียว) วิธีเดียวที่จะแน่ใจว่าฉันรู้จริง ๆ คือการทำmemsetบัฟเฟอร์ทั้งหมด ดูคำตอบต่อไปนี้สำหรับข้อมูลเพิ่มเติมstackoverflow.com/a/2688522/713554
Leo

45

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

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

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


31

จากความคิดเห็น HN นี้: https://news.ycombinator.com/item?id=6695581

เพียงแค่กรอก / dev / shm ผ่าน dd หรือคล้ายกัน

swapoff -a
dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k

8
ไม่ใช่ * nixes ทั้งหมดที่มี / dev / shm ความคิดแบบพกพาใด ๆ เพิ่มเติม?
Tadeusz A. Kadłubowski

หากpvติดตั้งแล้วจะช่วยให้เห็นจำนวน:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Otheus

1
หากคุณต้องการความเร็ววิธีนี้เป็นตัวเลือกที่ถูกต้อง! เพราะมันจัดสรรจำนวน RAM ที่ต้องการในไม่กี่วินาที อย่าส่งต่อ / dev / urandom มันจะใช้ CPU 100% และใช้เวลาหลายนาทีถ้า RAM ของคุณมีขนาดใหญ่ YET, / dev / shm มีขนาดสัมพัทธ์ใน distros Ubuntu / Debian ที่ทันสมัยมีขนาดที่มีค่าเริ่มต้นเป็น 50% ของ RAM จริง หวังว่าคุณสามารถติดตั้งใหม่ / dev / shm หรืออาจสร้างจุดเชื่อมต่อใหม่ ตรวจสอบให้แน่ใจว่ามีขนาดจริงตามที่คุณต้องการจัดสรร
develCuy


24

ถ้าคุณมีเครื่องมือ GNU พื้นฐาน ( sh, grep, yesและhead) ที่คุณสามารถทำเช่นนี้:

yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily

สิ่งนี้ทำงานได้เนื่องจาก grep โหลดข้อมูลทั้งหมดใน RAM (ฉันได้เรียนรู้สิ่งนี้ในทางที่ค่อนข้างโชคร้ายเมื่อทำการ grepping ดิสก์อิมเมจ) บรรทัดที่สร้างโดยyes, การขึ้นบรรทัดใหม่เปลี่ยนจะมีความยาวเพียบ แต่ถูก จำกัด ด้วยheadการ$BYTESไบต์จึง grep จะโหลด $ ไบต์ในหน่วยความจำ Grep ใช้ตัวเองเช่น 100-200KB สำหรับฉันคุณอาจต้องลบมันออกเพื่อให้ได้ปริมาณที่แม่นยำยิ่งขึ้น

หากคุณต้องการเพิ่มการ จำกัด เวลาก็สามารถทำได้อย่างง่ายดายในbash(จะไม่ทำงานsh):

cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n

<(command)สิ่งที่ดูเหมือนจะเป็นที่รู้จักกันเล็ก ๆ น้อย ๆ แต่บ่อยครั้งที่เป็นประโยชน์อย่างยิ่งข้อมูลเพิ่มเติมเกี่ยวกับมันที่นี่: http://tldp.org/LDP/abs/html/process-sub.html

จากนั้นสำหรับการใช้cat: catจะรอให้อินพุตดำเนินการจนจบและโดยการเปิดท่อใดท่อหนึ่งก็จะทำให้ grep ยังมีชีวิตอยู่

หากคุณมีpvและต้องการเพิ่มการใช้ RAM อย่างช้าๆ:

yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n

ตัวอย่างเช่น:

yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n

จะใช้มากถึงกิกะไบต์ในอัตรา 1MB ต่อวินาที เป็นโบนัสเพิ่มเติมpvจะแสดงอัตราการใช้ปัจจุบันและการใช้ทั้งหมดจนถึงปัจจุบัน แน่นอนว่าสิ่งนี้สามารถทำได้กับตัวแปรรุ่นก่อนหน้า:

yes | tr \\n x | head -c $BYTES | pv | grep n

เพียงแค่การแทรก| pv |ส่วนจะแสดงสถานะปัจจุบัน (ปริมาณงานและยอดรวมตามค่าเริ่มต้นฉันคิดว่า - ไม่เช่นนั้นจะเห็นหน้า man (ual))


ทำไมต้องมีคำตอบอื่นอีก? คำตอบที่ได้รับการยอมรับแนะนำให้ติดตั้งแพคเกจ (ฉันพนันได้เลยว่าจะมีการเปิดตัวชิปเซ็ตทุกชุดโดยไม่จำเป็นต้องมีผู้จัดการแพ็คเกจ) คำตอบที่ได้รับคะแนนสูงสุดแนะนำให้รวบรวมโปรแกรม C (ฉันไม่ได้ติดตั้งคอมไพเลอร์หรือ Toolchain เพื่อรวบรวมสำหรับแพลตฟอร์มเป้าหมายของคุณ); คำตอบที่ได้รับการโหวตอันดับสองแนะนำให้รันแอปพลิเคชั่นใน VM (ใช่แล้วขอให้ฉันใช้ sdcard ภายในของโทรศัพท์นี้ผ่าน usb หรืออะไรซักอย่างแล้วสร้างภาพ virtualbox); ที่สามแนะนำการแก้ไขบางสิ่งบางอย่างในลำดับการบู๊ตที่ไม่เติม RAM ตามที่ต้องการ ส่วนที่สี่ใช้งานได้เฉพาะในจุดที่ / dev / shm mountpoint (1) มีอยู่และ (2) มีขนาดใหญ่ (จำเป็นต้องมีการรูทใหม่) ที่ห้ารวมหลายอย่างโดยไม่มีรหัสตัวอย่าง; คำตอบที่หกเป็นคำตอบที่ดี แต่ฉันไม่เห็นคำตอบนี้ก่อนที่จะเข้าหาวิธีการของตัวเอง ดังนั้นฉันคิดว่าฉันจะเพิ่มของตัวเองเพราะมันสั้นกว่าที่จะจำหรือพิมพ์ทับหากคุณไม่เห็นว่าบรรทัด memblob นั้นเป็นประเด็นสำคัญของเรื่องนี้ ที่เจ็ดอีกครั้งไม่ตอบคำถาม (ใช้ ulimit เพื่อ จำกัด กระบวนการแทน); ที่แปดพยายามให้คุณติดตั้งหลาม; เก้าคิดว่าเราทุกคนไม่สร้างสรรค์มากและในที่สุดสิบก็เขียนโปรแกรม C ++ ของเขาเองซึ่งทำให้เกิดปัญหาเดียวกันกับคำตอบที่ได้รับการโหวตสูงสุด


ทางออกที่น่ารัก ความผิดพลาดเพียงอย่างเดียวคือรหัสทางออกของการสร้างคือ 1 เนื่องจาก grep ไม่พบการจับคู่ ไม่มีวิธีแก้ปัญหาใด ๆ จากstackoverflow.com/questions/6550484/…ดูเหมือนจะแก้ไข
Holger Brandl

@ HolgerBrandl จุดที่ดีฉันไม่ทราบวิธีการแก้ไข ครั้งนี้เป็นครั้งแรกที่ผมได้ยินset -eดังนั้นฉันเพิ่งได้เรียนรู้บางสิ่งบางอย่าง :)
ลัค

$ SECONDS ดูเหมือนจะไม่เป็นตัวเลือกที่ดีเนื่องจากเป็นตัวแปรในตัวที่สะท้อนเวลาตั้งแต่เริ่มต้นเชลล์ ดูtldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Holger Brandl

@ HolgerBrandl จับดีฉันไม่ทราบว่า ค่อนข้างเย็นเมื่อต้องการค้นหาเทอร์มินัลที่เปิดให้บริการในปัจจุบัน> 3 ล้านวินาที: D ฉันอัพเดทโพสต์แล้ว
Luc

เทคนิคเจ๋ง! time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n(ใช้หน่วยความจำ 10 GiB) ใช้เวลา 1 นาที 46 วินาที ใช้งานโปรแกรม eatmemory ของ julman99 ที่github.com/julman99/eatmemoryใช้เวลา 6 วินาที ... รวมทั้งเวลาในการดาวน์โหลดและรวบรวม แต่มันรวบรวมโดยไม่มีปัญหา ... และเร็วมาก ... บนเครื่อง RHEL6.4 ของฉัน ยังฉันชอบวิธีนี้ ทำไมต้องคิดค้นล้อใหม่
Mike S

18

ฉันใช้ฟังก์ชันทำสิ่งที่คล้ายกันในดอทไฟล์ของฉัน https://github.com/sagotsky/.dotfiles/blob/master/.functions#L248

function malloc() {
  if [[ $# -eq 0 || $1 -eq '-h' || $1 -lt 0 ]] ; then
    echo -e "usage: malloc N\n\nAllocate N mb, wait, then release it."
  else 
    N=$(free -m | grep Mem: | awk '{print int($2/10)}')
    if [[ $N -gt $1 ]] ;then 
      N=$1
    fi
    sh -c "MEMBLOB=\$(dd if=/dev/urandom bs=1MB count=$N) ; sleep 1"
  fi
}

1
นี่คือทางออกที่ดีที่สุด IMHO เนื่องจากจำเป็นต้องใช้งาน dd เท่านั้นสิ่งอื่น ๆ ทั้งหมดสามารถแก้ไขได้ในเชลล์ใด ๆ โปรดทราบว่าจริง ๆ แล้วมันอ้างว่าหน่วยความจำสองครั้งกว่าข้อมูล dd ผลิตอย่างน้อยก็ชั่วคราว ทดสอบกับ debian 9, ขีดกลาง 0.5.8-2.4 ถ้าคุณใช้ bash สำหรับการรันชิ้นส่วน MEMBLOB มันจะช้ามากและใช้สี่เท่าของจำนวนที่ dd สร้าง
P.Péter

16

วิธีลดความซับซ้อนของโซลูชันหลามอย่างง่าย ๆ ?

#!/usr/bin/env python

import sys
import time

if len(sys.argv) != 2:
    print "usage: fillmem <number-of-megabytes>"
    sys.exit()

count = int(sys.argv[1])

megabyte = (0,) * (1024 * 1024 / 8)

data = megabyte * count

while True:
    time.sleep(1)

7
นั่นอาจจะถูกสับเปลี่ยนออกไปอย่างรวดเร็วโดยมีผลกระทบน้อยมากต่อความกดดันของหน่วยความจำ (เว้นแต่คุณจะเติมการแลกเปลี่ยนทั้งหมดเช่นกันซึ่งจะใช้เวลาสักครู่โดยปกติ)
Joachim Sauer

1
ทำไมการสลับยูนิกซ์ในขณะที่มี RAM ว่าง นี่เป็นวิธีที่เป็นไปได้ในการขับแคชดิสก์เมื่อมีความจำเป็น
Alexander Shcheblikin

@AlexanderShcheblikin คำถามนี้ไม่ได้เกี่ยวกับการสร้างดิสก์แคช (ซึ่งมีประโยชน์สำหรับการทดสอบประสิทธิภาพ แต่ไม่ใช่สำหรับการทดสอบทรัพยากรต่ำ)
Gilles

1
วิธีแก้ปัญหานี้ใช้งานได้หนึ่งหรือสองตัวในการทดสอบแม้ว่าฉันจะไม่พยายามเน้นความทรงจำก็ตาม แต่ @JoachimSauer คุณสามารถตั้งค่าได้sysctl vm.swappiness=0และตั้งค่า vm.min_free_kbytes เป็นจำนวนน้อยอาจจะ 1024 ฉันยังไม่ได้ลอง แต่ doc บอกว่านี่เป็นวิธีที่คุณควบคุมความรวดเร็วในการแลกเปลี่ยน ... คุณควรจะ สามารถทำให้มันค่อนข้างช้าไปจนถึงจุดที่ทำให้เกิดสภาวะ OOM บนเครื่องของคุณ ดูkernel.org/doc/Documentation/sysctl/vm.txtและkernel.org/doc/gorman/html/understand/understand005.html
Mike S

เพียงหนึ่งซับสำหรับ 1GB: python -c "x = (1 * 1024 * 1024 *
1024/8

10

ramfs ถ้ามันมีอยู่แล้วล่ะ? ติดตั้งและคัดลอกไฟล์ขนาดใหญ่หรือไม่ หาก/dev/shmไม่มี ramfs ไม่และ - ฉันเดาโปรแกรม C เล็ก ๆ ที่ทำ malloc ขนาดใหญ่ตามค่าอินพุตบางอย่าง? อาจต้องเรียกใช้สองสามครั้งในระบบ 32 บิตพร้อมหน่วยความจำจำนวนมาก


8

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


2
ที่จริงแล้วสิ่งนี้ไม่ทำงานบน linux (ไม่ทราบเกี่ยวกับ * nixes อื่น ๆ ) man setrlimit:RLIMIT_RSS Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM). This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.
Patrick

4

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


3

ฉันเขียนโปรแกรม C ++ ตัวน้อยสำหรับสิ่งนี้: https://github.com/rmetzger/dynamic-ballooner

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

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