Отключить убийцу Linux OOM по умолчанию?

37

Убийца OOM в Linux время от времени наносит ущерб различным приложениям, и кажется, что на самом деле мало что сделано на стороне разработчиков ядра, чтобы улучшить это. Не лучше ли в качестве наилучшей практики при настройке нового сервера отменить настройку по умолчанию при чрезмерной загрузке памяти, то есть отключить ее ( vm.overcommit_memory=2), если вы не уверены, что хотите включить ее для своего конкретного использования? И каковы будут те случаи использования, когда вы знаете, что хотите использовать чрезмерную загрузку?

В качестве бонуса, так как поведение в случае vm.overcommit_memory=2зависит от vm.overcommit_ratioпространства подкачки и пространства подкачки, что было бы хорошим эмпирическим правилом для определения размеров последних двух, чтобы вся эта установка продолжала работать разумно?

Питер Айзентраут
источник

Ответы:

63

Интересная аналогия (с http://lwn.net/Articles/104179/ ):

Авиакомпания обнаружила, что дешевле летать на самолетах с меньшим количеством топлива на борту. Самолеты были бы легче и потребляли бы меньше топлива, и деньги были сэкономлены. Однако в редких случаях количество топлива было недостаточным, и самолет падал. Эта проблема была решена инженерами компании путем разработки специального механизма OOF (без топлива). В экстренных случаях пассажира отбирали и выбрасывали из самолета. (При необходимости процедура повторялась.) Была разработана большая теория, и многие публикации были посвящены проблеме правильного выбора жертвы, подлежащей изгнанию. Должна ли жертва быть выбрана случайным образом? Или выбрать самого тяжелого человека? Или самый старый? Если пассажиры платят, чтобы их не выбросили, чтобы жертва была самой бедной на борту? И если, например, был выбран самый тяжелый человек, должно ли быть специальное исключение в случае, если это был пилот? Должны ли быть освобождены пассажиры первого класса? Теперь, когда OOF-механизм существует, он будет время от времени активироваться и выбрасывать пассажиров, даже когда не было нехватки топлива. Инженеры все еще изучают, как именно эта неисправность вызвана.

Эндрю
источник
11
Мне очень понравилось, спасибо, что выкопали это.
Ник Болтон
32

Убийца OOM наносит ущерб, только если вы перегрузили свою систему. Дайте ему достаточно свопа, и не запускайте приложения, которые вдруг решают съесть огромное количество оперативной памяти, и у вас не возникнет проблем.

Чтобы конкретно ответить на ваши вопросы:

  • Я не думаю, что это хорошая идея, чтобы отключить overcommit в общем случае; очень немногие приложения написаны для правильной работы с brk(2) (и обертками, которые его используют, такими как malloc(3)), возвращающими ошибку. Когда я экспериментировал с этим на моей предыдущей работе, было больше хлопот, чтобы получить все, что способно обрабатывать ошибки нехватки памяти, чем просто бороться с последствиями OOM (который, в нашем случае, было гораздо хуже, чем перезапускать случайный сервис, если произошла OOM - нам пришлось перезагрузить весь кластер, потому что GFS - это испаряющаяся куча фекалий).
  • Вы хотите включить overcommit для любого процесса, который перегружает память. Двумя наиболее распространенными виновниками здесь являются Apache и JVM, но множество приложений делают это в большей или меньшей степени. Они думают, что в будущем им может понадобиться много памяти, поэтому они сразу же получают большой кусок. В системе с поддержкой overcommit ядро ​​говорит: «Что угодно, приходите беспокоить меня, когда вы действительно хотите писать на эти страницы», и ничего плохого не происходит. В отключенной системе ядро ​​говорит: «Нет, у вас не может быть такого большого количества памяти, если вам случится что-то написать в какой-то момент в будущем, я буду костей, так что памяти для вас нет!» и распределение не удается. Так как ничеготам идет "о, хорошо, я могу иметь этот меньший объем сегмента данных процесса?", тогда процесс либо (а) завершается с ошибкой нехватки памяти, либо (б) не проверяет код возврата из malloc думает, что все в порядке, и записывает данные в недопустимую область памяти, вызывая segfault. К счастью, JVM выполняет все предварительное выделение при запуске (поэтому ваша JVM либо запускается, либо умирает немедленно, что вы обычно замечаете), но Apache делает все с приколом с каждым новым дочерним элементом, что может привести к захватывающим эффектам в работе (невоспроизводимым), не обрабатывая соединения «виды возбуждения».
  • Я бы не хотел устанавливать значение overcommit_ratio выше, чем значение по умолчанию, равное 50%. Опять же, из моих тестов, хотя установка 80 или 90 может показаться крутой идеей, ядру требуются большие куски памяти в неудобное время, а в полностью загруженной системе с высоким коэффициентом перегрузок, скорее всего, будет недостаточно свободной памяти когда ядро ​​нуждается в этом (приводя к страху, эпидемии и упадкам). Таким образом, игра с overcommit представляет новый, еще более забавный режим сбоя - вместо того, чтобы просто перезапускать любой процесс, получивший OOMed, когда у вас заканчивается память, теперь ваша машина падает, что приводит к отключению всего на машине. ЗДОРОВО!
  • Пространство подкачки в системе без перегрузки зависит от того, сколько запрошенной, но неиспользуемой памяти требуется вашим приложениям, плюс здоровый запас безопасности. Выработка того, что необходимо в конкретном случае, оставлена ​​читателю в качестве упражнения.

По сути, мой опыт показывает, что отключение overcommit - это хороший эксперимент, который редко работает так же хорошо на практике, как звучит в теории. Это прекрасно согласуется с моим опытом работы с другими переменными в ядре - разработчики ядра Linux почти всегда умнее вас, и настройки по умолчанию работают лучше всего в подавляющем большинстве случаев. Оставьте их в покое, и вместо этого найдите, в каком процессе произошла утечка, и устраните ее.

romble
источник
2
Я не хочу, чтобы мой процесс резервного копирования был убит, потому что кто-то делает мой веб-сервер. Исключения хороши, но по умолчанию должны быть безопасность и последовательность. Оптимизации типа OOM должны быть включены вручную ИМХО. Это как кодирование, вы кодируете чисто, а затем оптимизируете. Over-commit - хорошая функция, но не должна быть по умолчанию.
Аки
1
Если вы не хотите, чтобы процесс резервного копирования был убит из-за того, что кто-то делает ваш веб-сервер DoS, не настраивайте ваш веб-сервер таким образом, чтобы DoS мог привести к перегрузке ресурсов в системе.
Уомбл
У меня 8 ГБ ОЗУ, и только запуск Firefox и виртуальная машина иногда приводят к тому, что OOM-убийца убивает ВМ. Компилируя Unreal Engine 4, каждый вызов clang занимает 1 ~ 1.5 ГБ памяти, и снова, OOM killer время от времени убивает один. Теперь я в целом согласен с этим, без убийцы OOM они, вероятно, в любом случае будут сегфолтами. Просто всякий раз, когда OOM killer хочет убить процесс, моя система зависает на 10 минут, прежде чем плохой процесс будет фактически убит. Ошибка возможно? Скорее всего. Хочу ли я этого? Точно нет. И это ваша причина, почему кто-то может захотеть отключить убийцу OOM.
Шахбаз
1
Если вы делаете все это на коробке, вам нужно больше оперативной памяти, а отключение overcommit только усугубит ситуацию.
Бен Лютгенс
6

Хм, я не полностью убежден аргументами в пользу сверхкоммитов и убийцы OOM ... Когда womble пишет,

«Убийца OOM наносит ущерб только в том случае, если вы перегружаете свою систему. Дайте ей достаточно подкачки, и не запускайте приложения, которые вдруг решают съесть огромное количество оперативной памяти, и у вас не возникнет проблем».

Он посвящен описанию сценария среды, в котором сверхкоммитирование и OOM killer не применяются или не действуют "по-настоящему" (если все приложения выделяют память по мере необходимости и имеется достаточно виртуальной памяти для распределения, записи в память будут следовать за распределением памяти без ошибки, поэтому мы не могли говорить о слишком загруженной системе, даже если была включена стратегия избыточной загрузки). Речь идет о неявном признании, что overcommit и OOM killer работают лучше всего, когда их вмешательство не требуется, что, насколько я могу судить, так или иначе разделяется большинством сторонников этой стратегии (и я признаю, что не могу сказать много ...). Более того, обращение к приложениям с определенным поведением при предварительном распределении памяти заставляет меня думать, что конкретная обработка может быть настроена на уровне распределения вместо использования по умолчанию,

Что касается JVM, то это виртуальная машина, в какой-то степени ей нужно выделять все ресурсы, которые ей нужны при запуске, чтобы она могла создать свою «поддельную» среду для своих приложений и держать свой доступный ресурс отдельно от хоста. среда, насколько это возможно. Таким образом, может быть предпочтительнее иметь сбой при запуске, а не через некоторое время как следствие «внешнего» состояния OOM (вызванного чрезмерной передачей / OOM killer / что угодно), или в любом случае страдать от такого условия, мешающего его собственному стратегии внутренней обработки OOM (как правило, виртуальная машина должна получать любые необходимые ресурсы с самого начала, а хост-система должна «игнорировать» их до конца, точно так же, как никогда не используется любое количество физической памяти, разделяемое с графической картой, - и не может быть - тронут ОС).

Что касается Apache, я сомневаюсь, что время от времени убивать и перезапускать весь сервер лучше, чем позволить одному дочернему элементу, а также одному соединению, потерпеть неудачу с самого начала (= дочернего / подключения) (как если бы это был совершенно новый экземпляр JVM, созданная после запуска другого экземпляра некоторое время). Я думаю, что лучшее «решение» может зависеть от конкретного контекста. Например, если рассматривать службу электронной коммерции, может быть гораздо предпочтительнее иметь иногда несколько случайных неудачных соединений с графиком покупок, чем потерять весь сервис, с риском, например, прервать текущее завершение заказа или (может быть, хуже) процесс оплаты со всеми последствиями дела (может быть, безвредным, но, возможно, вредным - и, конечно, когда возникли проблемы,

Точно так же на рабочей станции процесс, который потребляет наибольшее количество ресурсов и, таким образом, является первым выбором для убийцы OOM, может быть приложением с интенсивным использованием памяти, таким как транскодер видео или программное обеспечение для рендеринга, вероятно, единственное приложение пользователь хочет быть нетронутым. Эти соображения намекают на то, что политика OOM killer по умолчанию слишком агрессивна. Он использует подход «наихудшего соответствия», который как-то похож на подход некоторых файловых систем (OOMK старается освободить как можно больше памяти, уменьшая при этом количество уничтоженных подпроцессов, чтобы предотвратить любое дальнейшее вмешательство в короткие сроки, так как кроме того, fs может выделить больше дискового пространства, чем фактически необходимо для определенного файла, чтобы предотвратить дальнейшее распределение, если файл вырос, и, таким образом, в некоторой степени предотвратить фрагментацию).

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

Более того, может быть неверно, что убийство меньшего количества возможных процессов - это всегда хороший выбор. Например, в среде рабочего стола (для примера давайте подумаем о неттопе или нетбуке с ограниченными ресурсами) пользователь может запустить браузер с несколькими вкладками (таким образом, он потребляет память - допустим, это первый выбор для OOMK) плюс несколько других приложений (текстовый процессор с несохраненными данными, почтовый клиент, программа для чтения PDF, медиаплеер, ...), плюс несколько (системных) демонов, а также несколько экземпляров файлового менеджера. Теперь происходит ошибка OOM, и OOMK решает убить браузер, пока пользователь делает что-то, что считается «важным» в сети ... пользователь будет разочарован. С другой стороны, закрытие нескольких файловых менеджеров

В любом случае, я думаю, что пользователь должен иметь возможность самостоятельно принимать решение о том, что ему делать. В настольной (= интерактивной) системе это должно быть относительно легко сделать, при условии, что зарезервировано достаточно ресурсов, чтобы попросить пользователя закрыть любое приложение (но даже закрытия нескольких вкладок может быть достаточно) и обработать его выбор (вариант может состоят из создания дополнительного файла подкачки, если места достаточно). Что касается сервисов (и вообще), я бы также рассмотрел еще два возможных усовершенствования: одно - протоколирование вмешательств OOM-убийцы, а также процессы, запускающие / блокирующие сбои, таким образом, что сбой может быть легко отлажен (например, API может информировать процесс, инициирующий создание нового процесса или разветвление - таким образом, такой сервер, как Apache, с соответствующим патчем, может обеспечить лучшую регистрацию для определенных ошибок); это может быть сделано независимо от предпринимаемых сверхкоммитов / OOMK; во-вторых, но не для важности, можно было бы создать механизм для точной настройки алгоритма ООМК - я знаю, что возможно, в некоторой степени, определить конкретную политику для процесса в отдельности, но я бы хотел «централизованный» механизм конфигурации, основанный на одном или нескольких списках имен приложений (или идентификаторов) для идентификации соответствующих процессов и придания им определенной степени важности (согласно перечисленным атрибутам); такой механизм должен (или, по крайней мере, мог бы) также быть многоуровневым, чтобы мог быть пользовательский список верхнего уровня, системный (распределение) определенный список и (нижний уровень) определенные пользователем записи (так например, файловый менеджер DE может дать OOMK команду безопасно уничтожить любой экземпляр,

Более того, API может быть предоставлен для того, чтобы позволить приложениям повышать или понижать свой уровень «важности» во время выполнения (с точки зрения управления памятью и независимо от приоритета выполнения), так что, например, процессор Word может запускаться с низкая «важность», но повышайте ее, поскольку некоторые данные хранятся перед сбросом в файл, или выполняется операция записи, и снова снижаете важность, когда такая операция завершается (аналогично, файловый менеджер может изменить уровень, когда он передается из простого использование файлов для работы с данными и наоборот вместо использования отдельных процессов, и Apache может дать разные уровни важности различным дочерним элементам или изменить дочернее состояние в соответствии с некоторой политикой, выбранной системными администраторами и раскрытой через Apache - или любой другой тип сервера. - настройки). Конечно, такой API может и будет злоупотреблять / злоупотреблять, но я думаю, что это небольшая проблема по сравнению с тем, как ядро ​​произвольно убивает процессы для освобождения памяти без какой-либо соответствующей информации о том, что происходит в системе (и о потреблении памяти / времени создания или подобной области). «не достаточно релевантен или« проверяет »для меня) - только пользователи, администраторы и составители программ могут реально определить, является ли процесс« по-прежнему необходимым »по какой-то причине, какова причина и / или находится ли приложение в ведущем состоянии к потере данных или другим повреждениям / проблемам, если их убить; тем не менее, можно сделать некоторое предположение, например, поиск ресурсов определенного типа (файловые дескрипторы, сетевые сокеты и т. д.), полученных процессом, и с ожидающими операциями может сказать, должен ли процесс находиться в более высоком «состоянии», чем один набор,

Или просто избегайте чрезмерной загрузки и позвольте ядру делать то, что должно делать ядро, выделяя ресурсы (но не спасая их произвольно, как это делает убийца OOM), планируя процессы, предотвращая голодание и взаимные блокировки (или спасая от них), обеспечивая полное прерывание и разделение памяти, и так далее ...

Я также потратил бы еще несколько слов о подходах сверхкоммитов. Из других обсуждений я высказал мысль о том, что одна из основных проблем, связанных с чрезмерной фиксацией (как причина этого хотеть, так и источник возможных проблем), заключается в обработке вилок: честно говоря, я не знаю, как именно Стратегия «при записи» реализована, но я думаю, что любая агрессивная (или оптимистичная) политика может быть смягчена с помощью стратегии локального обмена. То есть вместо простого клонирования (и настройки) разветвленных кодовых страниц процесса и структур планирования можно скопировать несколько других страниц данных перед фактической записью, выбрав среди этих страниц родительский процесс, к которому более часто обращались для записи (то есть использование счетчика для операций записи).

Всё, конечно, ИМХО.


источник
5
«Более того, API может быть предоставлен для того, чтобы позволить приложениям повышать или понижать свой уровень« важности »во время выполнения» /proc/$PID/oom_adj.
Ви.
1
Что касается JVM, то есть недочёт, в некоторых случаях вы хотите, чтобы память была перегружена: если вы хотите создать другую JVM из вашей исходной JVM, она вызовет fork (). Вызов вилки будет выделять столько памяти, сколько исходный процесс (первый), пока он действительно не запустит процесс. Допустим, у вас есть 4 ГБ JVM и вы хотите создать из него новую 512 КБ JVM, если для этого не требуется
чрезмерная загрузка
4
@Vi. Кажется, сейчас/proc/$PID/oom_score_adj
m3nda
1

Если ваша память исчерпана процессами настолько, что может угрожать стабильности системы, тогда появляется убийца OOM. Задачей OOM Killer является уничтожение процессов до тех пор, пока не освободится достаточно памяти для бесперебойного функционирования остальной части процесса. OOM Killer должен выбрать «лучший» процесс для уничтожения. «Лучший» здесь относится к тому процессу, который высвободит максимум памяти при убийстве, а также наименее важен для системы. Основная цель состоит в том, чтобы убить наименьшее количество процессов, которое минимизирует наносимый ущерб и в то же время максимизирует количество освобождаемой памяти. Чтобы облегчить это, ядро ​​поддерживает oom_score для каждого из процессов. Вы можете увидеть oom_score каждого из процессов в файловой системе / proc в каталоге pid

# cat /proc/10292/oom_score

Чем выше значение oom_score любого процесса, тем выше вероятность того, что OOM Killer будет убит в ситуации нехватки памяти.

Кредит: - Ядро Linux запускает убийцу OOM

Динки Джанвар
источник