Что: 17efdb3c97a8de4227c447bd8dc67cbbd7ae873b Когда: 2021-05-17 20:33:20+03:00 ------------------------------------------------------------------------ Темы: bsd djb ------------------------------------------------------------------------ Ограничения процесса по памяти и процессору https://unix.stackexchange.com/questions/44985/limit-memory-usage-for-a-single-linux-process http://coldattic.info/post/40/ ulimit-ом я пользовался прежде только для подкручивания кол-ва файловых дескрипторов. Регулярно во многих задачах в них утыкался. Недавно в goredo, в котором я много открытых файлов без надобности имел. Но вот по памяти никогда не приходилось ограничивать. И я так и не понял как с этим работать и почему оно не работает. Говорю маленький "ulimit -m", но что Go, что Си программы упорно спокойно могут аллоцировать гигабайты. Судя по stackexchange, оно или у кого-то работает, или предлагают совершенно другие решения. Вот и я пока совершенно не знаю как оно всё устроено и почему не работает. Но, как всегда, на помощь пришёл софт от DJB! Помню что в daemontools была утилита по ограничению ресурсов. "softlimit -m" отлично срабатывает, возвращая ошибку нехватки памяти. И для Go софта отрабатывает без проблем. Обратил внимание на то, что можно ограничить CPU время через этот softlimit. Проверил -- действительно это не время жизни процесса, а именно съеденное время. Посетила идея что надо бы lighttpd обернуть в эту штуку -- раз в несколько месяцев, но замечаю что иногда lighttpd отжирает 100% CPU, вроде даже ни на что и не реагируя (но не помню точно). Поставил перезапуск по cron. Как раз softlimit по процессору вроде бы должен помочь: при штатной работе он не много ест CPU и его наверное неделями можно было бы не перезапускать, а если он уйдёт в бесконечный цикл, то быстро иссякнет лимит и его грохнут, автоматически перезапустив. А вообще тут возился с одной программой, которая жутко течёт. Сейчас выбросил её, но вот не понравилось мне то, что при росте памяти оно начнёт отъедать swap и, соответственно, делать систему неработоспособной. А если OOM killer и сработает, то запросто грохнет какой-нибудь SSH. Знаю что это вечная проблема и придумана тьмища способов решения или, хотя бы, выбора кого надо грохнуть. Но сейчас вот вижу что можно просто бы обернуть в softlimit недоверенный (или известно что текучий) софт и не париться. Где-то я вроде у DJB в его скудной документации видел совет по оборачиванию в softlimit -- теперь дошло насколько это полезно. Unix познаётся мною только сейчас... А ещё в статье на coldattic.info упоминается что soft limit-ы пошлют сигнал SIGCPU, который можно перехватить и как-то среагировать. Знал что есть soft и hard, но даже примерно не представлял чем они на практике бы отличались. Впрочем у меня всё равно ulimit никоим образом не отрабатывает (или я делаю что-то не так). ------------------------------------------------------------------------ оставить комментарий: mailto:comment@blog.stargrave.org?subject=Re:%20%D0%9E%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%B0%20%D0%BF%D0%BE%20%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8%20%D0%B8%20%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80%D1%83%20%2817efdb3c97a8de4227c447bd8dc67cbbd7ae873b%29 ------------------------------------------------------------------------ комментарий 0: From: kmeaw Date: 2021-05-17 20:01:04Z > Говорю маленький "ulimit -m", но > что Go, что Си программы упорно спокойно могут аллоцировать гигабайты. ulimit -d 16384 -s 16384 -l 16384 -m 16384 (data, stack, mlocked & resident memory) После этого ни mmap, ни (s)brk не выделяют память. > А если OOM killer и сработает, то запросто грохнет > какой-нибудь SSH. Обычно для этого подкручивают oom_adj для sshd, чтобы его грохали в последнюю очередь. А браузеры, в свою очередь, подкручивают в обратную сторону oom_adj для процессов-вкладок, чтобы их OOM killer убивал первыми. > Знал что есть soft и hard, но даже примерно не представлял чем они на > практике бы отличались. Реально на процесс действует soft limit. Hard limit - административное ограничение, выше которого soft limit поднять нельзя. На практике администраторы обычно для почти всех ресурсов ставят soft limit равным hard limit, а на файловые дескрипторы soft limit делают меньше hard limit в несколько раз. Если программа знает про resource limits, то она временно опустит soft limit до необходимого минимума или поднимет soft limit на открытые файловые дескрипторы, если, например, это какой-нибудь нагруженный сетевой сервис. > Впрочем у меня всё равно ulimit никоим образом не > отрабатывает (или я делаю что-то не так). odin% zsh --version zsh 5.4.2 (x86_64--netbsd) odin% ulimit -t 5 odin% while true; do :; done Connection to sdf-eu.org closed. ------------------------------------------------------------------------ комментарий 1: From: Sergey Matveev Date: 2021-05-18 07:24:23Z *** kmeaw [2021-05-17 22:59]: >ulimit -d 16384 -s 16384 -l 16384 -m 16384 >После этого ни mmap, ни (s)brk не выделяют память. Похоже я совсем не знаю как всё устроено и работает с памятью. Я вот написал вот такое: int main(void) { int i = 0; while (true) { if (malloc(10*(1<<20)) == NULL) { abort(); }; usleep(10000); printf("%d\n", i++); }; return 0; } Сделал ulimit как у вас (только без -l, ибо у меня hard-limit сильно меньше) и смотрю в top, дошло до: PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND 38174 stargrave 1 20 0 43G 20M nanslp 0 0:00 0.35% main Размер виртуальной памяти огромный -- понимаю ещё почему может быть, это не напрягает. Хотя я считал что malloc то уж должен быть RES-ом, а всякие SIZE учитывают mmap-нутые файлы например. У меня zsh 5.6.2, FreeBSD 12.0, но, как видно, всё равно даже RES достиг больше чем 16MiB указанных в ulimit и ничего не падает. Или ulimit влияет только и только на сам shell, но не его детей? Буду читать про это. Ибо ваш пример с -t 5 то у меня честно отрабатывает. >Обычно для этого подкручивают oom_adj для sshd, чтобы его грохали в >последнюю очередь. А браузеры, в свою очередь, подкручивают в обратную >сторону oom_adj для процессов-вкладок, чтобы их OOM killer убивал >первыми. Наслышан, наслышан. Сам правда ни с чем таким ни разу не встречался. >Реально на процесс действует soft limit. Hard limit - административное >ограничение, выше которого soft limit поднять нельзя. >На практике администраторы обычно для почти всех ресурсов ставят soft >limit равным hard limit Спасибо за информацию! С этим всем пока ещё в курсе. ------------------------------------------------------------------------ комментарий 2: From: Sergey Matveev Date: 2021-05-18 09:49:15Z У коллеги под bash и Gentoo какой-то тоже ничего не вышло. Вроде у меня всё встаёт на свои места почему не работало. man setrlimit говорит что: RLIMIT_RSS When there is memory pressure and swap is available, prioritize eviction of a process' resident pages beyond this amount (in bytes). When memory is not under pressure, this rlimit is effectively ignored. Even when there is memory pressure, the amount of available swap space and some sysctl settings like vm.swap_enabled and vm.swap_idle_enabled can affect what happens to processes that have exceeded this size. Processes that exceed their set RLIMIT_RSS are not signalled or halted. The limit is merely a hint to the VM daemon to prefer to deactivate pages from processes that have exceeded their set RLIMIT_RSS. то есть RLIMIT_RSS никому не скажет ENOMEM и ничего не сделает. RLIMIT_DATA The maximum size (in bytes) of the data segment for a process; this defines how far a program may extend its break with the sbrk(2) function. влияет только честно на sbrk. Но у меня из коробки используется jemalloc, который использует по умолчанию для больших блоков mmap, а не sbrk, который не учитывается RLIMIT_DATA. В итоге у нас получилось ограничить память только по RLIMIT_VMEM, который как-раз и делает (в том числе) softlimit из daemontools. ------------------------------------------------------------------------ комментарий 3: From: kmeaw Date: 2021-05-18 20:08:09Z Проверил программу из комментария 1 на разных ОС. Linux 4.19, 5.2.11, 5.4.31, 5.10.27: ломается сразу, напечатав "0". NetBSD 9.1: не ломается, быстро растёт SIZE, медленно растёт RES. Если добавить bzero на выделяемую память, то начинает быстро расти RES. Возможно, что реализация malloc у NetBSD вызывает mmap без BSD-аналога MAP_POPULATE, отдавая "непрогретые" странички. При таком вызове страница будет выделена "по-настоящему" тогда, когда её потрогают. В Linux это можно отключить настройкой vm.overcommit_ratio=0, но этого делать не рекомендуется, потому что многие программы расчитывают на такое поведение. В Windows такого нет, зато драйверы ядра умеют уходить в своп. FreeBSD 13.0-RELEASE, тоже не ломается. Без bzero растёт SIZE, поведение аналогично NetBSD. OpenBSD 6.9: ломается сразу, напечатав "0". Вариант с RLIMIT_VMEM мне не очень нравится, потому что на 64-битных платформах нет особого смысла экономить адресное пространство, а лимитируемая программа может при нормальной работе отображать (non-anonymous mmap) большие файлы на память, не приводя к расходу резидентной памяти. Но, похоже, что на BSD без этого никак, так как "[t]he limit is merely a hint". А в OpenBSD вовсе нет RLIMIT_VMEM (или аналога, как RLIMIT_AS в Linux). Попытался включить rctl, но настройка user:foo:memoryuse:deny=40m тоже не ломает эту программу. user:foo:vmemoryuse:deny=40m работает, так же, как и RLIMIT_VMEM. Но можно написать правило для monit, которое будет следить и перезапускать прожорливую программу. > limit влияет только и только на сам shell, но не его детей? При execve resource limits наследуются от родителя, но могут быть изменены дочерним процессом для себя. В Linux ещё есть prlimit, который позволяет менять resource limits чужим процессам (если есть capability CAP_SYS_RESOURCE). ------------------------------------------------------------------------ комментарий 4: From: Sergey Matveev Date: 2021-05-18 20:38:03Z *** kmeaw [2021-05-18 23:06]: >Linux 4.19, 5.2.11, 5.4.31, 5.10.27: ломается сразу, напечатав "0". У коллеги с Gentoo не знаю что за версии ядра, но было такое же поведение как у меня -- ни разу не "сломалось", пока VMEM не ограничили. >Если добавить bzero на выделяемую память, то начинает быстро расти RES. Ага, это тоже проделывали на Gentoo. С этим оно действительно начинает есть память, а не просто "резервировать" с неспешным ростом RES. >В Linux это можно отключить настройкой vm.overcommit_ratio=0, но этого >делать не рекомендуется, потому что многие программы расчитывают на >такое поведение. Во-во, именно про overcommit я и подумал и понимаю что поведение "непрогретых" страниц связано с ним. >Вариант с RLIMIT_VMEM мне не очень нравится Вот и мне тоже. Я поэтому всё что касается VMEM-а и не трогал и не пробовал. Плюс ещё можно mmap-ать файлы, что тоже не имеет смысла ограничивать. >Но можно написать правило для monit, которое будет >следить и перезапускать прожорливую программу. Ну это уже совсем костыль, так сказать. Работать то конечно будет, если процесс не разрастётся в окне между проверками monit. Завтра попробую ограничить в Jail-е через rctl. https://wiki.freebsd.org/JailResourceLimits вроде бы можно RSS ограничивать. ------------------------------------------------------------------------ комментарий 5: From: Sergey Matveev Date: 2021-05-19 10:02:59Z *** Sergey Matveev [2021-05-18 23:38]: >ограничить в Jail-е через rctl Ограничение по RSS работает... top показывает что процесс более не вылезает за указанный лимит. Вот только размер виртуальной памяти при этом всё равно упорно продолжает расти. Сейчас использую цикл с malloc-ами и arc4random заполнением этих страниц, чтобы точно там были недедуплицируемые данные. В общем, я не вижу как можно было бы ограничить размер памяти в FreeBSD, кроме как только ограничением размера виртуальной. ------------------------------------------------------------------------ Сгенерирован: SGBlog 0.34.0