35

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

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

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

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

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

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

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

5)

1 ответ1

34

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 . Например:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .