Что: 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 никоим образом не отрабатывает (или я делаю что-то не так).
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.
From: Sergey Matveev Date: 2021-05-18 07:24:23Z
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.
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).
From: Sergey Matveev Date: 2021-05-18 20:38:03Z
From: Sergey Matveev Date: 2021-05-19 10:02:59Z
Сгенерирован: SGBlog 0.34.0