Предотвратить зависание системы / не отвечает из-за перестановки использования памяти
Если процесс требует много памяти, система перемещает все остальные процессы в файл подкачки. В том числе вроде бы необходимые процессы вроде сервера X11 или терминала.
Таким образом, если процесс продолжает выделяться без ограничений, все перестает отвечать, пока этот процесс не будет убит OOM-киллером. Мой ноутбук кажется особенно чувствительным и реагирует крайне плохо. Я просто потратил ВЕСЬ ЧАС, ожидая завершения процесса, во время которого даже курсор мыши не мог быть перемещен.
Как этого можно избежать?
1) Отключить своп => Я часто запускаю множество процессов, которые затем становятся неактивными. Неактивные должны быть перемещены в своп.
2) Получить SSD => слишком дорого
3) установить максимальный объем памяти ulimit =>, но в случае сбоя программы требуется большой объем памяти. проблема не в том, что он использует слишком много, а в том, что он подавляет другие процессы
4) хранить важные программы (X11, bash, kill, top, ...) в памяти и никогда не менять их => это можно сделать? как? возможно только обменять большие программы?
5)
1 ответ
TL;DR
Краткий временный ответ
- Самый простой: иметь меньший раздел подкачки и избегать попыток ядра оправдать ложь о том, что нет ограничений памяти при запуске процессов из медленного хранилища.
- С большой заменой OOM (из менеджера памяти) не предпринимает действий достаточно скоро. Как правило, он учитывается в соответствии с виртуальной памятью и, по моему прошлому опыту, не убивал вещи до тех пор, пока не был заполнен весь своп, отсюда и система обхода и обхода...
- Нужен большой своп на спящий режим?
- Попытка / проблема: установить некоторые ограничения (например, проверить
ulimit -v
и, возможно, установите жесткий или мягкий предел, используяas
вариант вlimits.conf
). Раньше это работало достаточно хорошо, но благодаря внедрению WebKitgigacage
многие приложения gnome теперь ожидают неограниченного адресного пространства и не запускаются! - Попытка / проблема: политика и соотношение чрезмерного принятия обязательств - это еще один способ попытаться справиться с этим и смягчить его (например,
sysctl vm.overcommit_memory
,sysctl vm.overcommit_ratio
, но этот подход не сработал для меня. - Сложно / сложно: Попробуйте применить приоритет cgroup к наиболее важным процессам (например, ssh), но в настоящее время это кажется громоздким для cgroup v1 (надеюсь, v2 облегчит это)...
- Попытка / проблема: установить некоторые ограничения (например, проверить
Я также нашел:
- другая запись обмена стека, которая подтверждает приведенный выше совет для меньшего пространства подкачки.
- Вы можете попробовать что-то вроде thrash-protect как обходной путь для текущей ситуации.
Долгосрочное решение
подождите и надейтесь, что некоторые апстрим-патчи попадут в стабильные ядра дистрибутива. Также надеемся, что производители дистрибутивов лучше настроят параметры ядра по умолчанию и лучше используют системные группы 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% дополнительного использования памяти и 10% снижения производительности (вероятно, в отношении операций выделения памяти - на самом деле это не указано).
- 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
с учетом всего графического стека рабочего стола и приложений в нем, тем не менее, вылетает.