TL; DR
Краткий временный ответ
- Самый простой : иметь меньший раздел подкачки и избегать попыток ядра оправдать ложь о том, что нет ограничений памяти при запуске процессов из медленного хранилища.
- С большой заменой OOM (из менеджера памяти) не предпринимает действий достаточно скоро. Как правило, он учитывается в соответствии с виртуальной памятью и, по моему прошлому опыту, не убивал вещи до тех пор, пока не был заполнен весь своп, отсюда и система обхода и обхода ...
- Нужен большой своп на спящий режим?
- Попытка / проблема : Установите некоторые ограничения (например, проверьте
ulimit -v
, и, возможно, установите жесткий или мягкий предел, используяas
опцию вlimits.conf
). Раньше это работало достаточно хорошо, но благодаря внедрению WebKitgigacage
многие приложения gnome теперь ожидают неограниченного адресного пространства и не запускаются! - Покушение / проблематично : Политика overcommit и соотношение это еще один способ, чтобы попытаться управлять и уменьшить это (например
sysctl vm.overcommit_memory
,sysctl vm.overcommit_ratio
, но этот подход не работает для меня. - Сложно / сложно : Попробуйте применить приоритет cgroup к наиболее важным процессам (например, ssh), но в настоящее время это кажется громоздким для cgroup v1 (надеюсь, v2 облегчит это) ...
- Попытка / проблема : Установите некоторые ограничения (например, проверьте
Я также нашел:
- другая запись обмена стека, которая подтверждает приведенный выше совет для меньшего пространства подкачки .
- Вы можете попробовать что-то вроде thrash-protect как обходной путь для текущей ситуации.
Долгосрочное решение
подождите и надейтесь, что некоторые апстрим-патчи попадут в стабильные ядра дистрибутива. Также надеемся, что производители дистрибутивов лучше настроят параметры ядра по умолчанию и улучшат использование системных 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% дополнительного использования памяти и 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
учитывая, что графический стек всего настольного компьютера и приложения в нем все равно аварийно завершают работу.