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

11663
BeniBela

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

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

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

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

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

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

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

5)

29
И это случилось снова :( Запустил gcc во время работы firefox, все было заблокировано на полчаса. Никаких движений мыши, никаких электронных книг BeniBela 7 лет назад 0
Я не уверен, что понимаю, чего вы хотите. Вы хотите, чтобы система волшебным образом делала вещи быстрее с имеющимися ресурсами? Вы хотите убить процессы, которые используют много памяти раньше? David Schwartz 7 лет назад 0
Похоже, что вам действительно нужно больше оперативной памяти. Или менее «неактивные» фоновые задачи. Daniel B 7 лет назад 0
Вы можете использовать комбинацию клавиш [Alt + SysRq + F] (https://www.reddit.com/r/linux/comments/75gyrz/a_tribute_to_altsysrqf/), чтобы запустить OOM-killer. Это может сократить лишнее время, необходимое для того, чтобы ваша система открыла консоль, чтобы вы могли завершить процесс. hololeap 6 лет назад 0
Поправьте меня, если я ошибаюсь, но на самом деле эта проблема звучит так, как будто система ищет место на диске, которое должно существовать, но не существует (раздел подкачки слишком мал). Недостаточно места подкачки приведет к тому, что система «перегрузит» жесткий диск (или ssd) в поисках свободного места. mchid 6 лет назад 0

1 ответ на вопрос

27
JPvRiel

TL; DR

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

  • Самый простой : иметь меньший раздел подкачки и избегать попыток ядра оправдать ложь о том, что нет ограничений памяти при запуске процессов из медленного хранилища.
    • С большой заменой OOM (из менеджера памяти) не предпринимает действий достаточно скоро. Как правило, он учитывается в соответствии с виртуальной памятью и, по моему прошлому опыту, не убивал вещи до тех пор, пока не был заполнен весь своп, отсюда и система обхода и обхода ...
  • Нужен большой своп на спящий режим?
    • Попытка / проблема : Установите некоторые ограничения (например, проверьте ulimit -v, и, возможно, установите жесткий или мягкий предел, используя asопцию в limits.conf). Раньше это работало достаточно хорошо, но благодаря внедрению WebKit gigacageмногие приложения gnome теперь ожидают неограниченного адресного пространства и не запускаются!
    • Покушение / проблематично : Политика overcommit и соотношение это еще один способ, чтобы попытаться управлять и уменьшить это (например 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 . Например:

  • 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 хранилища, чтобы избежать конкуренции с процессами. заняты обменом. Функции ядра и приоритета ввода / вывода уже давно существуют. Вроде бы приоритетного доступа к физической ОЗУ не хватает.

Однако даже приоритеты процессора и ввода-вывода не установлены должным образом !? Насколько я могу судить, когда я проверял пределы 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учитывая, что графический стек всего настольного компьютера и приложения в нем все равно аварийно завершают работу.

Это лучшая рецензия, которую я видел по этому вопросу, и вы не прибегаете к «просто купите больше оперативной памяти!» Одна вещь, которую вы не упоминаете, это то, как параметры конфигурации ядра играют в этом. Например, будет ли используемая модель preemtion или планировщик ввода / вывода иметь какое-либо существенное влияние на это? hololeap 6 лет назад 0
`но ядро ​​не сможет использовать избыточную стратегию для выделения памяти, и это, вероятно, снизит производительность. Это позволяет даже меньший раздел подкачки. Есть ли доказательства этому? Я считаю, что ядро ​​перегрузит просто отлично без настроенного свопа ygrek 5 лет назад 1
@ygrek, спасибо, что формулировка выглядит немного неправильно - overcommit по-прежнему работает без подкачки, если не выбран режим never overcommit (2). Эвристический режим overcommit по умолчанию (0) или режим всегда commit (1), вероятно, по-прежнему работают без подкачки. Не могу вспомнить, где я читал, что отключение свопа вредит способности кода overcommit выделять память (и какой режим это затрагивало конкретно). Снова погуглил без удачи, но это был полу-полезный пост: https://stackoverflow.com/questions/38688824/linux-over-commit-heuristic Я отредактирую ответ соответствующим образом. JPvRiel 5 лет назад 0
Я надеялся, что патч фоновой обратной записи поможет мне, но я нахожусь на очень новом ядре (4.14.81) и сталкиваюсь со значительными проблемами отзывчивости при тяжелом вводе-выводе диска (независимо от того, является ли своп причиной причиной или нет). Интересно, не вызывает ли какой-либо проблемы с производительностью менеджер устройств или мое шифрование LUKS? Я действительно мало знаю, как отладить такого рода проблемы. Darius Jahandarie 5 лет назад 0