Як заповнити 90% вільної пам'яті?


181

Я хочу зробити тестування з низькими ресурсами, і для цього мені потрібно заповнити 90% вільної пам'яті.

Як я можу це зробити в *nixсистемі?


3
Чи дійсно потрібно працювати в будь-якій системі * nix?
CVn

31
Замість того, щоб запам'ятовувати запам'ятовувальну пам'ять, ви могли б створити VM (використовуючи докер, бродягу чи щось подібне) з обмеженою кількістю пам'яті?
абендіго

4
@abendigo Для QA багато з представлених тут рішень корисні: для ОС загального призначення без конкретної платформи параметри завантаження VM або ядра можуть бути корисними, але для вбудованої системи, де ви знаєте специфікацію пам'яті цільової системи, я б перейдіть на заповнення вільної пам'яті.
Едуард Флорінеску

2
У випадку, якщо хтось ще трохи шокований очками тут: meta.unix.stackexchange.com/questions/1513/… ?
goldilocks

Дивіться також: unix.stackexchange.com/a/1368/52956
Вільф

Відповіді:


156

stress-ng - це генератор робочого навантаження, який імітує напругу процесора / mem / io / hdd для 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
Роберт

1
Більшу частину MemFree зберігає ОС, тому я використовував MemAvailable замість цього. Це дало мені 92% використання в Cent OS 7.stress --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нічого не робить, і вас можуть ввести в оману, ви можете виділити стільки пам'яті, скільки вам потрібно / хочете. Мене це покусало, поки я не намагався перевірити себе, виділивши 256 Гб пам'яті. Це не вада у відповіді, вона забезпечує правильні прапори, просто додаткову обережність.
примхливий

Ось чому є -m 1. За даними, що стосується стресу, -m Nце скорочення --vm N: нерестові Nробітники, що malloc()/free()
прямують

92

Ви можете написати програму C malloc()на потрібну пам'ять, а потім використовувати, mlock()щоб запобігти заміні пам'яті.

Тоді просто дозвольте програмі чекати введення клавіатури та розблокувати пам’ять, звільнити пам'ять та вийти.


25
Давно мені довелося перевірити подібний випадок використання. Я зауважував, що поки ти щось не запишеш у цю пам'ять, вона фактично не буде виділена (тобто, доки не станеться помилка сторінки). Я не впевнений, чи mlock () піклується про це.
Poorna

2
Я погоджуюся з @siri; однак це залежить від того, який варіант UNIX ви використовуєте.
Ентоні

2
Деяке натхнення для коду. Крім того, я думаю, вам не потрібно розблокувати / звільнити пам'ять . ОС закінчить це для вас, коли ваш процес закінчиться.
Себастьян

9
Вам, мабуть, доведеться насправді записати в пам’ять, ядро ​​може просто перезапустити, якщо ви лише зрадите його. Якщо налаштовано, наприклад, Linux дозволить malloc успішно повертатися, не маючи фактично вільної пам'яті, і лише фактично розподіляє пам'ять, коли вона записується. Дивіться win.tue.nl/~aeb/linux/lk/lk-9.html
Bjarke Freund-Hansen

7
@Sebastian: зіткнеться callocз тією ж проблемою IIRC. Вся пам'ять буде просто вказувати на одну і ту ж сторінку з нульовим читанням. Він фактично не буде виділений, поки ви не спробуєте записати на нього (що не спрацює, оскільки це лише для читання). Єдиний спосіб бути впевненим у тому, що я знаю, - це зробити memsetвесь буфер. Дивіться наступну відповідь для отримання додаткової інформації stackoverflow.com/a/2688522/713554
Лев

45

Я б запропонував запустити VM з обмеженою пам’яттю та протестувати програмне забезпечення, що було б більш ефективним тестом, ніж спроба заповнити пам'ять на хост-машині.

Цей метод також має перевагу в тому, що якщо ситуація з низькою пам'яттю спричиняє помилки OOM в іншому місці і вішає всю ОС, ви вішаєте лише те, що ви тестуєте, на машину, яку ви не перевіряєте, на вашу машину.

Крім того, якщо тестування не є процесорним або IO інтенсивним, ви можете одночасно запускати екземпляри тестів на сімействі VM з різними низькими розмірами пам'яті.


31

З цього коментаря до НН: 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. Якась більш портативна ідея?
Тадеуш А. Кадлубовський

Якщо pvвстановлено, це допомагає побачити кількість:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Отей

1
Якщо ви хочете швидкості, цей спосіб - правильний вибір! Тому що він виділяє бажану кількість оперативної пам’яті за лічені секунди. Не вмикайте / dev / urandom, якщо ваш об'єм оперативної пам’яті буде великим, він використовуватиме 100% процесора та займе кілька хвилин. І все-таки / dev / shm має відносний розмір у сучасних дистрибутивах Ubuntu / Debian, він має розмір, який за замовчуванням становить 50% фізичної оперативної пам’яті. Сподіваємось, ви зможете повторно переробити / dev / shm або, можливо, створити нову точку монтажу. Просто переконайтеся, що він має фактичний розмір, який ви хочете виділити.
develCuy

30
  1. запустити Linux;
  2. завантаження з mem=nn[KMG]параметром завантаження ядра

(детальну інформацію див. у linux / Documentation / kernel-parametri.txt).


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 завантажує весь рядок даних в оперативній пам’яті (я дізнався це досить невдало, коли знімав образ диска). Лінії, генерується 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буде чекати, коли входи завершаться до виходу, і, тримаючи одну з труб відкритою, вона збереже жир.

Якщо у вас є pvі хочете повільно збільшувати використання оперативної пам’яті:

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

Використовуватиме до гігабайт зі швидкістю 1 МБ в секунду. Як додатковий бонус, pvпокаже вам поточну норму використання та загальне використання до цих пір. Звичайно, це можна зробити і з попередніми варіантами:

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

Просто вставлення | pv |частини покаже вам поточний стан (пропускний і загальний за замовчуванням, я думаю - інакше дивіться сторінку man (ual)).


Чому інша відповідь? Прийнята відповідь рекомендує встановити пакет (я вважаю, що є випуск для кожного чіпсета, не потребуючи менеджера пакунків); відповідь, що голосує вгорі, рекомендує скласти програму C (у мене не було встановлено компілятор чи інструментальну ланцюжок для компіляції для вашої цільової платформи); друга відповідь, проголосована вгорі, рекомендує запустити додаток у віртуальній машині (так, дозвольте мені просто занести внутрішню sdcard цього телефону через usb чи щось подібне та створити образ virtualbox); третій пропонує змінити щось у послідовності завантаження, що не заповнює оперативну пам'ять за бажанням; четвертий працює лише в тому випадку, коли існує точка встановлення / dev / shm (1) і (2) велика (перепланування потребує кореня); п’яте поєднує багато вищезазначеного без зразкового коду; шостий - чудова відповідь, але я не бачив цієї відповіді, перш ніж придумати власний підхід, тому я подумав, що я додаю своє, також тому, що це коротше запам’ятовувати або надрукувати, якщо ви не бачите, що лінія мембрани - це насправді суть справи; сьомий знову не відповідає на питання (використовує ulimit для обмеження процесу замість цього); восьма намагається змусити вас встановити python; дев'ятий вважає, що ми всі дуже нетворчі, і, нарешті, десятий написав свою власну програму C ++, яка викликає ту саму проблему, що і відповідь, яка проголосувала вгорі.


прекрасне рішення. Тільки глюк полягає в тому, що вихідний код конструкції дорівнює 1, оскільки grep не знаходить відповідності. Жодне з рішень stackoverflow.com/questions/6550484/…, здається, не виправляє це.
Холгер Брандл

@HolgerBrandl Добре, я не знаю, як це виправити. Про це я вперше почув set -e, тому я просто щось дізнався :)
Люк

$ SECONDS не здається вдалим вибором, оскільки це вбудована змінна, що відображає час з часу запуску оболонки. дивіться tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Holger Brandl

@HolgerBrandl Добрий улов, я цього не знав. Якимось приколом знайти термінал, який зараз відкритий протягом 3 мільйонів секунд: D Я оновив публікацію.
Люк

Класна техніка! time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n(використовуйте 10 Гб пам'яті) займає 1 хвилину 46 секунд. Запуск програми jumman99 на їжу на сайті github.com/julman99/eatmemory займає 6 секунд. ... Ну, плюс час завантаження та компіляції, але він збирався без проблем ... і дуже швидко ... на моїй машині RHEL6.4. Все-таки мені подобається таке рішення. Навіщо винаходити колесо?
Майк 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
Це найприємніше рішення ІМХО, оскільки воно, по суті, потребує лише роботи ДД, всі інші речі можна обробляти в будь-якій оболонці. Зауважте, що він фактично вимагає вдвічі більше пам’яті, ніж дані, які видає, принаймні тимчасово. Тестований на 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
Це, ймовірно, швидко буде замінено, матиме дуже невеликий фактичний вплив на тиск пам'яті (якщо тільки ви не заповните також усю заміну, яка зазвичай потребує певного часу)
Йоахім Зауер

1
Чому Unix підміняється, коли є доступна оперативна пам’ять? Це насправді правдоподібний спосіб виселення кеш-диска при необхідності.
Олександр Щеблікін

@AlexanderShcheblikin Це питання не стосується вилучення кеш-диска (який корисний для тестування продуктивності, але не для тестування низьких ресурсів).
Жиль

1
Це рішення спрацювало, щоб обмацувати концерт або два в моїх тестах, хоча я не намагався підкреслити свою пам'ять. Але, @JoachimSauer, можна було б встановити sysctl vm.swappiness=0і, крім того, встановити vm.min_free_kbytes на невелику кількість, можливо, 1024. Я цього не пробував, але документи говорять, що саме так ви контролюєте швидкість заміни ... ви повинні бути вдалося зробити це досить повільно, до того, щоб викликати стан OOM на вашій машині. Дивіться на kernel.org/doc/Documentation/sysctl/vm.txt та kernel.org/doc/gorman/html/understand/understand005.html
Майк S

просто один вкладиш на 1 Гб: 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.
Патрік

4

Я думаю, що це випадок задати неправильне запитання і заглушити людей, які змагаються за найкреативнішу відповідь. Якщо вам потрібно лише моделювати умови OOM, вам не потрібно заповнювати пам'ять. Просто використовуйте спеціальний розподільник, і він не вийде після певної кількості виділень. Цей підхід, здається, працює досить добре для SQLite .


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.