TL; DR
Краткий временный ответ
- Самый простой: иметь меньший раздел подкачки и избегать попыток ядра оправдать ложь о том, что нет ограничений памяти при запуске процессов из медленного хранилища.
- С большой заменой OOM (из менеджера памяти) не предпринимает действий достаточно скоро. Как правило, он учитывается в соответствии с виртуальной памятью и, по моему прошлому опыту, не убивал вещи до тех пор, пока не был заполнен весь своп, отсюда и система обхода и обхода ...
- Нужен большой своп на спящий режим?
- Попытка / проблема: Установите некоторые ulimits (например, проверьте
ulimit -v
, и, возможно, установите жесткий или мягкий предел, используя опцию as
в limits.conf
). Раньше это работало достаточно хорошо, но благодаря WebKit, внедряющему gigacage
, многие приложения gnome теперь ожидают неограниченного адресного пространства и не могут работать!
- Попытка / проблема: политика и соотношение чрезмерной передачи - это еще один способ попытаться управлять и смягчить это (например,
sysctl vm.overcommit_memory
, sysctl vm.overcommit_ratio
, но этот подход не сработал для меня.
- Сложно / сложно: Попробуйте применить приоритет cgroup к наиболее важным процессам (например, ssh), но в настоящее время это кажется громоздким для cgroup v1 (надеюсь, v2 облегчит это) ...
Я также нашел:
Долгосрочное решение
подождите и надейтесь, что некоторые апстрим-патчи попадут в стабильные ядра дистрибутива. Также надеемся, что производители дистрибутивов лучше настроят параметры ядра по умолчанию и улучшат использование системных cgroups для определения приоритетов отзывчивости GUI в настольных версиях.
Некоторые интересные участки:
Так что виноват не просто плохой код пользовательского пространства и конфигурация / настройки по умолчанию для дистрибутива - ядро справится с этим лучше.
Комментарии к уже рассмотренным вариантам
1) Отключить своп
Рекомендуется предусмотреть хотя бы небольшой раздел подкачки (нужен ли нам подкачка в современных системах?). Отключение подкачки не только предотвращает выгрузку неиспользуемых страниц, но также может повлиять на стратегию эвристического превышения по умолчанию в ядре для выделения памяти (что означает эвристика в Overcommit_memory = 0?), Поскольку эта эвристика рассчитывает на страницы подкачки. Без свопа overcommit все еще может работать в эвристическом (0) или всегда (1) режимах, но сочетание стратегии no swap и never (2) overcommit, вероятно, является ужасной идеей. Так что в большинстве случаев никакой своп, скорее всего, не повредит производительности.
Например, подумайте о длительном процессе, который первоначально затрагивает память для однократной работы, но затем не может освободить эту память и продолжает работать в фоновом режиме. Ядро должно будет использовать RAM для этого, пока процесс не закончится. Без какого-либо обмена ядро не может выгнать его из-за чего-то, что действительно хочет активно использовать оперативную память. Также подумайте о том, сколько разработчиков ленивы и явно не освобождают память после использования.
3) установить максимальный объем памяти ulimit
Это применимо только к процессу, и, вероятно, разумно предположить, что процесс не должен запрашивать больше памяти, чем у системы физически! Так что, вероятно, полезно, чтобы одинокий сумасшедший процесс не вызывал побои, пока все еще великодушно настроен.
4) хранить важные программы (X11, bash, kill, top, ...) в памяти и никогда не менять их
Хорошая идея, но тогда эти программы заберут память, которую они активно не используют. Это может быть приемлемо, если программа запрашивает только скромный объем памяти.
В выпуске systemd 232 только что добавлены некоторые опции, которые делают это возможным: я думаю, что можно использовать MemorySwapMax = 0, чтобы не допустить замены какой-либо части памяти (службы) типа ssh.
Тем не менее, возможность приоритезировать доступ к памяти была бы лучше.
Длинное объяснение
Ядро linux более приспособлено для серверных рабочих нагрузок, поэтому отзывчивость GUI, к сожалению, была вторичной проблемой ... Настройки управления памятью ядра в настольной версии Ubuntu 16.04 LTS, похоже, не отличались от других серверных выпусков. Он даже соответствует значениям по умолчанию в RHEL/CentOS 7.2, обычно используемом в качестве сервера.
OOM, ulimit и обмен целостности на отзывчивость
Перестановка перестановки (когда рабочий набор памяти, т. Е. Страницы, считываемые и записываемые в заданный короткий промежуток времени, превышают физическую ОЗУ), всегда блокирует ввод-вывод хранилища - никакое ядро ядра не может спасти систему от этого, не убивая процесс или два ...
Я надеюсь, что настройки Linux OOM, появившиеся в более новых ядрах, распознают, что этот рабочий набор превышает физическую память и убивает процесс. Когда этого не происходит, возникает проблема с молотом. Проблема в том, что с большим разделом подкачки это может выглядеть так, как будто система все еще имеет запас мощности, в то время как ядро весело выполняет коммиты и все еще обслуживает запросы памяти, но рабочий набор может перетекать в раздел подкачки, эффективно пытаясь обработать хранилище так, как если бы это оперативка
На серверах он допускает снижение производительности из-за обдумывания, медленного, не теряющего данных, компромисса. На настольных компьютерах компромисс отличается, и пользователи предпочли бы небольшую потерю данных (жертвоприношение процессов), чтобы держать вещи отзывчивыми.
Это была хорошая комическая аналогия с OOM: oom_pardon, иначе не убивай мой xlock
Кстати, OOMScoreAdjust
- это еще одна системная опция, помогающая взвешивать и избегать процессов убийства OOM, которые считаются более важными.
буферизованная обратная запись
Я думаю, что « сделать фоновую обратную запись не отстой » поможет избежать некоторых проблем, когда процесс, из-за которого ОЗУ процесса вызывает другой обмен (запись на диск) и массовая запись на диск, останавливает все остальное, требующее ввода-вывода. Это не является причиной проблемы само по себе, но это добавляет к общей деградации реагирования.
ограничение ограничений
Одна из проблем с ulimits заключается в том, что ограничение учета применяется к адресному пространству виртуальной памяти (что подразумевает объединение как физического, так и пространства подкачки). Согласно man limits.conf
.
rss
maximum resident set size (KB) (Ignored in Linux 2.4.30 and
higher)
Поэтому установка ulimit для применения только к физическому использованию оперативной памяти больше не выглядит пригодной для использования. следовательно
as
address space limit (KB)
кажется, единственная уважаемая перестраиваемая.
К сожалению, как подробно описано на примере WebKit/Gnome, некоторые приложения не могут работать, если выделено виртуальное адресное пространство.
cgroups должен помочь в будущем?
В настоящее время это кажется громоздким, но возможно включить некоторые флаги cgroup ядра cgroup_enable=memory swapaccount=1
(например, в конфигурации grub), а затем попытаться использовать контроллер памяти cgroup для ограничения использования памяти.
У cgroups есть более продвинутые возможности ограничения памяти, чем у параметров ulimit. Примечания CGroup v2 намекают на попытки улучшить работу ulimits.
Объединенный учет памяти и обмена подкачкой и ограничение заменены реальным контролем над пространством подкачки.
Параметры CGroup могут быть установлены с помощью параметров управления ресурсами systemd .
Например:
Другие полезные опции могут быть
У них есть некоторые недостатки:
- Накладные расходы. В текущей документации докера кратко упоминается 1% дополнительного использования памяти и 10% снижения производительности (вероятно, в отношении операций выделения памяти - на самом деле это не указано).
- Cgroup/systemd в последнее время сильно переработан, поэтому поток вверх по течению подразумевает, что поставщики дистрибутивов Linux могут ждать, пока он установится первым.
В CGroup v2 они предлагают, чтобы memory.high
был хорошим вариантом для регулирования и управления использованием памяти группой процессов. Однако эта цитата предполагает, что для мониторинга ситуаций с нехваткой памяти требовалось больше работы (по состоянию на 2015 год).
Мера давления памяти - насколько сильно на рабочую нагрузку влияют из-за нехватки памяти - необходима, чтобы определить, нуждается ли рабочая нагрузка в большей памяти; К сожалению, механизм контроля давления памяти еще не реализован.
Учитывая, что инструменты пространства пользователя systemd и cgroup являются сложными, я не нашел простого способа установить что-то подходящее и использовать это дальше. Документация cgroup и systemd для Ubuntu невелика. Дальнейшая работа должна состоять в том, чтобы дистрибутивы с настольными выпусками использовали cgroups и systemd, чтобы под высоким давлением памяти компоненты ssh и X-Server/ менеджер окон получили более приоритетный доступ к ЦП, физической ОЗУ и IO хранилища, чтобы избежать конкуренции с процессами. заняты обменом. Функции ядра и приоритета ввода / вывода уже давно существуют. Вроде бы приоритетного доступа к физической ОЗУ не хватает.
Однако даже приоритеты процессора и ввода-вывода не установлены должным образом !? Насколько я могу судить, когда я проверял пределы cgroup systemd, общие ресурсы центрального процессора и т.д., Ubuntu не выпекала никаких предопределенных приоритетов. Например, я побежал:
systemctl show dev-mapper-Ubuntu\x2dswap.swap
Я сравнил это с тем же выводом для ssh, samba, gdm и nginx. Важные вещи, такие как графический интерфейс и консоль удаленного администратора, должны одинаково бороться со всеми другими процессами, когда происходит перегрузка.
Пример ограничений памяти у меня на 16 ГБ ОЗУ
Я хотел включить hibernate, поэтому мне нужен был большой раздел подкачки. Следовательно, попытка смягчить с помощью ulimits и т.д.
ULIMIT
Я поставил * hard as 16777216
в /etc/security/limits.d/mem.conf
, чтобы ни одному процессу не было разрешено запрашивать больше памяти, чем физически возможно. Я не буду препятствовать уничтожению всего вместе, но без этого, только один процесс с жадным использованием памяти или утечка памяти, может вызвать поражение. Например, я видел, как gnome-contacts
высасывают 8 ГБ + памяти при выполнении таких рутинных задач, как обновление глобального списка адресов с сервера обмена ...
Как видно из ulimit -S -v
, во многих дистрибутивах этот жесткий и мягкий лимит задан как «неограниченный», теоретически процесс может закончить запросом большого количества памяти, но только активно используя подмножество, и работать счастливо, думая, что ему дали скажем, 24 ГБ ОЗУ, а система имеет только 16 ГБ. Вышеуказанное жесткое ограничение приведет к тому, что процессы, которые могли бы нормально работать, прервутся, когда ядро откажется от своих жадных спекулятивных запросов памяти.
Тем не менее, он также ловит безумные вещи, такие как контакты gnome, и вместо того, чтобы терять отзывчивость моего рабочего стола, я получаю ошибку "недостаточно свободной памяти":
Сложности настройки ulimit для адресного пространства (виртуальная память)
К сожалению, некоторые разработчики любят притворяться, что виртуальная память - это бесконечный ресурс, и установка ограничения на виртуальную память может сломать некоторые приложения. Например, в WebKit (от которого зависят некоторые приложения gnome) добавлена функция безопасности gigacage
которая пытается распределить безумные объемы виртуальной памяти, и FATAL: Could not allocate gigacage memory
с дерзким намеком. Make sure you have not set a virtual memory limit
. Обходной путь , GIGACAGE_ENABLED=no
, не отменяет преимуществ безопасности, но также не позволяет ограничивать выделение виртуальной памяти, также отказывается от функции безопасности (например, контроль ресурсов, который может предотвратить отказ в обслуживании). По иронии судьбы, между разработчиками gigacage и gnome они, похоже, забывают, что ограничение выделения памяти само по себе является контролем безопасности. И, к сожалению, я заметил, что приложения gnome, основанные на gigacage, не удосуживаются явно запросить более высокий лимит, так что даже мягкий лимит нарушает ситуацию в этом случае.
Справедливости ради следует отметить, что если бы ядро справлялось с задачей запретить выделение памяти на основе использования резидентной памяти вместо виртуальной памяти, то притворная неограниченная виртуальная память была бы менее опасной.
overcommit
Если вы предпочитаете, чтобы приложениям было отказано в доступе к памяти, и вы хотите прекратить чрезмерную загрузку, используйте приведенные ниже команды, чтобы проверить, как ваша система ведет себя при высоком давлении в памяти.
В моем случае коэффициент фиксации по умолчанию был:
$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
Но он вступает в силу в полной мере только при изменении политики, чтобы отключить чрезмерную загрузку и применить соотношение
sudo sysctl -w vm.overcommit_memory=2
Отношение подразумевало, что всего 24 ГБ памяти может быть выделено в целом (16 ГБ ОЗУ * 0,5 + 16 ГБ SWAP). Таким образом, я, вероятно, никогда не увижу, что OOM будет отображаться, и, скорее всего, у процессов будет меньше доступа к памяти в процессе подкачки. Но я также, вероятно, пожертвую общей эффективностью системы.
Это приведет к сбою многих приложений, поскольку разработчики обычно не корректно обрабатывают ОС, отклоняя запрос на выделение памяти. Он обменивает случайный риск затягивания блокировки из-за перебора (потеря всей вашей работы после полной перезагрузки) и более частого риска сбоя различных приложений. В моем тестировании это не очень помогло, потому что сам рабочий стол рухнул, когда система находилась под давлением памяти и не могла выделить память. Однако, по крайней мере, консоли и SSH все еще работали.
Как VM overcommit память работает, есть больше информации.
Для этого я решил вернуться к значению по умолчанию, sudo sysctl -w vm.overcommit_memory=0
, учитывая весь графический стек рабочего стола и приложения в нем, тем не менее, аварийно завершают работу.