Предотвратить зависание системы / не отвечает из-за перестановки использования памяти

Если процесс требует много памяти, система перемещает все остальные процессы в файл подкачки. В том числе вроде бы необходимые процессы вроде сервера X11 или терминала.

Таким образом, если процесс продолжает выделяться без ограничений, все перестает отвечать, пока этот процесс не будет убит OOM-киллером. Мой ноутбук кажется особенно чувствительным и реагирует крайне плохо. Я просто потратил ВЕСЬ ЧАС, ожидая завершения процесса, во время которого даже курсор мыши не мог быть перемещен.

Как этого можно избежать?

1) Отключить своп => Я часто запускаю множество процессов, которые затем становятся неактивными. Неактивные должны быть перемещены в своп.

2) Получить SSD => слишком дорого

3) установить максимальный объем памяти ulimit =>, но в случае сбоя программы требуется большой объем памяти. проблема не в том, что он использует слишком много, а в том, что он подавляет другие процессы

4) хранить важные программы (X11, bash, kill, top, ...) в памяти и никогда не менять их => это можно сделать? как? возможно только обменять большие программы?

5)

1 ответ

Решение

TL;DR

Краткий временный ответ

  • Самый простой: иметь меньший раздел подкачки и избегать попыток ядра оправдать ложь о том, что нет ограничений памяти при запуске процессов из медленного хранилища.
    • С большой заменой OOM (из менеджера памяти) не предпринимает действий достаточно скоро. Как правило, он учитывается в соответствии с виртуальной памятью и, по моему прошлому опыту, не убивал вещи до тех пор, пока не был заполнен весь своп, отсюда и система обхода и обхода...
  • Нужен большой своп на спящий режим?
    • Попытка / проблема: установить некоторые ограничения (например, проверить ulimit -v и, возможно, установите жесткий или мягкий предел, используя as вариант в limits.conf). Раньше это работало достаточно хорошо, но благодаря внедрению WebKit gigacage многие приложения gnome теперь ожидают неограниченного адресного пространства и не запускаются!
    • Попытка / проблема: политика и соотношение чрезмерного принятия обязательств - это еще один способ попытаться справиться с этим и смягчить его (например, sysctl vm.overcommit_memory, sysctl vm.overcommit_ratio, но этот подход не сработал для меня.
    • Сложно / сложно: Попробуйте применить приоритет cgroup к наиболее важным процессам (например, ssh), но в настоящее время это кажется громоздким для cgroup v1 (надеюсь, v2 облегчит это)...

Я также нашел:

Долгосрочное решение

подождите и надейтесь, что некоторые апстрим-патчи попадут в стабильные ядра дистрибутива. Также надеемся, что производители дистрибутивов лучше настроят параметры ядра по умолчанию и лучше используют системные группы cd для определения приоритетов отзывчивости графического интерфейса в настольных версиях.

Некоторые интересные пятна:

Так что виноват не только плохой код пользовательского пространства и конфигурация / настройки по умолчанию для дистрибутива - ядро ​​справится с этим лучше.

Комментарии к уже рассмотренным вариантам

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 более приспособлено для серверных рабочих нагрузок, поэтому, к сожалению, отзывчивость графического интерфейса была второстепенной проблемой... Настройки управления памятью ядра в настольной версии Ubuntu 16.04 LTS, похоже, не отличались от других серверных выпусков. Он даже соответствует значениям по умолчанию в RHEL/CentOS 7.2, обычно используемом в качестве сервера.

OOM, ulimit и обмен целостности на отзывчивость

Перестановка перестановки (когда рабочий набор памяти, т. Е. Страницы, считываемые и записываемые в заданный короткий промежуток времени, превышают физическую ОЗУ), всегда блокирует ввод-вывод хранилища - никакое ядро ​​ядра не может спасти систему от этого, не убивая процесс или два...

Я надеюсь, что настройки Linux OOM, появившиеся в более новых ядрах, распознают, что этот рабочий набор превышает физическую память и убивает процесс. Когда этого не происходит, возникает проблема с молотом. Проблема в том, что с большим разделом подкачки это может выглядеть так, как будто система все еще имеет запас мощности, в то время как ядро ​​весело выполняет коммиты и по-прежнему обслуживает запросы памяти, но рабочий набор может перетекать в swap, эффективно пытаясь обработать хранилище так, как если бы это оперативная память

На серверах он допускает снижение производительности из-за обдумывания, медленного, без потери данных, компромисса. На настольных компьютерах компромисс отличается, и пользователи предпочли бы небольшую потерю данных (жертвоприношение процессов), чтобы держать вещи отзывчивыми.

Это была хорошая комическая аналогия с 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. Например:

  • MemoryHigh
  • MemoryMax

Другие полезные опции могут быть

  • IOWeight
  • CPUShares

У них есть некоторые недостатки:

  1. Накладные расходы. В текущей документации докера кратко упоминается 1% дополнительного использования памяти и 10% снижения производительности (вероятно, в отношении операций выделения памяти - на самом деле это не указано).
  2. Cgroup / systemd в последнее время сильно переработан, поэтому поток вверх по течению подразумевает, что поставщики дистрибутивов Linux могут ждать, пока он установится первым.

В CGroup v2 они предполагают, что memory.high должен быть хорошим вариантом для регулирования и управления использованием памяти группой процессов. Однако эта цитата предполагает, что для мониторинга ситуаций с нехваткой памяти требовалось больше работы (по состоянию на 2015 год).

Мера давления памяти - насколько сильно на рабочую нагрузку влияют из-за нехватки памяти - необходима, чтобы определить, нуждается ли рабочая нагрузка в большей памяти; К сожалению, механизм контроля давления памяти еще не реализован.

Учитывая, что инструменты пространства пользователя systemd и cgroup являются сложными, я не нашел простого способа установить что-то подходящее и использовать это в дальнейшем. Документация cgroup и systemd для Ubuntu невелика. Дальнейшая работа должна быть для дистрибутивов с настольными выпусками, чтобы использовать cgroups и systemd, чтобы под высоким давлением памяти компоненты ssh и X-Server/ менеджер окон получили более высокий приоритет доступа к ЦП, физической ОЗУ и IO хранилища, чтобы избежать конкуренции с процессами заняты обменом. Функции ядра и приоритета ввода / вывода уже давно существуют. Похоже, приоритетного доступа к физической ОЗУ не хватает.

Однако даже приоритеты процессора и ввода-вывода не установлены должным образом!? Когда я проверял ограничения systemd cgroup, общие ресурсы центрального процессора и т. Д., Насколько я могу судить, 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 ГБ + памяти при выполнении таких рутинных задач, как обновление глобального списка адресов с сервера Exchange...

Как видно с 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 с учетом всего графического стека рабочего стола и приложений в нем, тем не менее, вылетает.

Другие вопросы по тегам