Убийца OOM в Linux время от времени сеет хаос с различными приложениями, и кажется, что на стороне разработки ядра мало что сделано для улучшения этого. Не лучше ли, как лучшая практика при настройке нового сервер, чтобы отменить значение по умолчанию для чрезмерного выделения памяти, то есть выключить его (vm.overcommit_memory=2
) если вы не знаете, что хотите, чтобы это было для вашего конкретного использования? И каковы были бы эти варианты использования, если бы вы знали, что хотите, чтобы чрезмерные усилия?
В качестве бонуса, поскольку поведение в случае vm.overcommit_memory=2
зависит от vm.overcommit_ratio
и пространство подкачки, что было бы хорошим практическим правилом для определения размера последних двух, чтобы вся эта установка работала нормально?
Интересная аналогия (из http://lwn.net/Articles/104179/):
Авиакомпания обнаружила, что дешевле летать на самолетах с меньшим количеством топлива на борту. Самолеты будут легче и потребляют меньше топлива, и деньги будут сэкономлены. Однако в редких случаях количество топлива было недостаточным, и самолет терпел крушение. Эта проблема была решена инженерами компании разработкой специального механизма OOF (без топлива). В экстренных случаях был выбран и выброшен пассажир из самолета. (При необходимости процедуру повторяли.) Был разработан большой объем теории, и множество публикаций было посвящено проблеме правильного выбора жертвы для изгнания. Следует ли выбирать жертву случайным образом? Или выбирать самого тяжелого? Или самый старый? Должны ли пассажиры платить, чтобы их не выбросили, чтобы пострадавший был самым бедным на борту? А если, например, был выбран самый тяжелый человек, должно ли быть особое исключение в случае, если это был пилот? Должны ли быть освобождены пассажиры первого класса? Теперь, когда существует механизм OOF, он будет время от времени активироваться и катапультировать пассажиров, даже когда не было недостатка топлива. Инженеры все еще изучают, как именно вызвана эта неисправность.
Убийца OOM сеет хаос только в том случае, если вы перегрузили свою систему. Дайте ему достаточно подкачки и не запускайте приложения, которые внезапно решают съесть огромное количество оперативной памяти, и у вас не будет проблем.
Чтобы конкретно ответить на ваши вопросы:
brk
(2) (и обертки, которые его используют, например malloc
(3)) возвращает ошибку. Когда я экспериментировал с этим на моей предыдущей работе, было сочтено, что получить все, способное обрабатывать ошибки нехватки памяти было больше хлопот, чем просто справиться с последствиями OOM (что в нашем случае было намного хуже, чем перезапуск случайного сервиса в случае OOM - нам пришлось перезагрузить весь кластер, потому что GFS - это дымящаяся куча фекалий).По сути, мой опыт показывает, что отключение чрезмерной фиксации - это хороший эксперимент, который на практике редко работает так хорошо, как кажется в теории. Это хорошо согласуется с моим опытом с другими настройками в ядре - разработчики ядра Linux почти всегда умнее вас, а настройки по умолчанию лучше всего подходят для большинства, обширный в большинстве случаев. Оставьте их в покое, а вместо этого найдите, в каком процессе есть утечка, и устраните ее.
Хм, меня не до конца убеждают аргументы в пользу overcommit и OOM killer ... Когда womble пишет,
«Убийца OOM сеет хаос только в том случае, если вы перегружаете свою систему. Дайте ему достаточно подкачки и не запускайте приложения, которые внезапно решают съесть огромное количество оперативной памяти, и у вас не будет проблем».
Он описывает сценарий среды, в котором чрезмерная фиксация и убийца OOM не применяются или не действуют `` на самом деле '' (если все приложения выделяют память по мере необходимости и было достаточно виртуальной памяти для выделения, запись в память будет точно следовать выделению памяти без ошибок, поэтому мы не можем говорить о чрезмерно загруженной системе, даже если была включена стратегия чрезмерной загрузки). Речь идет о неявном признании того, что overcommit и OOM killer работают лучше всего, когда их вмешательство не требуется, что так или иначе разделяется большинством сторонников этой стратегии, насколько я могу судить (и я признаю, что не могу сказать много ...). Более того, обращение к приложениям с определенным поведением при предварительном выделении памяти заставляет меня думать, что конкретная обработка может быть настроена на уровне распределения, вместо того, чтобы иметь системный подход по умолчанию, основанный на эвристике (лично я считаю, что эвристический подход - не очень хороший подход. для ядра)
Что касается JVM, ну, это виртуальная машина, в какой-то степени ей нужно выделить все ресурсы, которые она потребности при запуске, так что он может создать свою «фальшивую» среду для своих приложений и держать доступный ресурс отдельно от среды хоста, насколько это возможно. Таким образом, может быть предпочтительнее иметь сбой при запуске, а не через некоторое время в результате `` внешнего '' состояния OOM (вызванного чрезмерной фиксацией / убийцей OOM / чем-то еще) или в любом случае страдать от такого состояния, мешающего его собственному внутренние стратегии обработки OOM (как правило, виртуальная машина должна получать все необходимые ресурсы с самого начала, а хост-система должна `` игнорировать '' их до конца, точно так же, как любое количество физической оперативной памяти, совместно используемой с видеокартой, никогда - и не может быть - тронул ОС).
Что касается Apache, я сомневаюсь, что время от времени убивать и перезапускать весь сервер лучше, чем позволить одному дочернему элементу вместе с одним соединением выйти из строя с его (= дочернего / соединения) начала (как если бы это был совершенно новый экземпляр JVM, созданная после некоторого запуска другого экземпляра). Думаю, лучшее «решение» может зависеть от конкретного контекста. Например, при рассмотрении службы электронной коммерции может быть гораздо предпочтительнее, чтобы иногда несколько подключений к диаграмме покупок выходили из строя случайным образом, вместо потери всей службы с риском, например, прервать текущее завершение заказа, или (может быть, хуже) процесс оплаты со всеми последствиями случая (может быть, безвреден, но может быть вреден - и, конечно, когда возникнут проблемы, это будет хуже, чем состояние невоспроизводимой ошибки для целей отладки).
Точно так же на рабочей станции процесс, который потребляет больше всего ресурсов и, следовательно, является первым выбором для убийцы OOM, может быть приложение, интенсивно использующее память, такое как транскодер видео, или программное обеспечение для рендеринга, вероятно, единственное приложение. пользователь хочет, чтобы его не трогали. Эти соображения намекают мне, что политика убийцы OOM по умолчанию слишком агрессивна. Он использует подход «наихудшего соответствия», который чем-то похож на подход некоторых файловых систем (OOMK пытается освободить как можно больше памяти, уменьшая при этом количество убитых подпроцессов, чтобы предотвратить дальнейшее вмешательство в короткие сроки, поскольку ну, так как fs может выделить больше дискового пространства, чем фактически необходимо для определенного файла, чтобы предотвратить дальнейшее выделение, если файл увеличился и, таким образом, предотвращая фрагментацию в некоторой степени).
Однако я думаю, что противоположная политика, такая как подход `` наилучшего соответствия '', может быть предпочтительнее, чтобы освободить именно ту память, которая требуется в определенный момент, и не беспокоиться о `` больших '' процессах, которые вполне могут быть напрасными. памяти, но также может и не знать, и ядро не может этого знать (хм, я могу представить, что отслеживание количества обращений к странице и времени может намекнуть, выделяет ли процесс память, которая ему больше не нужна, поэтому, чтобы угадать, будет ли процесс тратит память или просто использует много, но задержки доступа должны быть взвешены по циклам процессора, чтобы отличить потерю памяти от памяти и приложение с интенсивным использованием ЦП, но, хотя такая эвристика потенциально неточна, она может иметь чрезмерные накладные расходы).
Более того, может быть неправда, что уничтожение меньшего числа возможных процессов - всегда хороший выбор. Например, в среде рабочего стола (давайте представим неттоп или нетбук с ограниченными ресурсами, для примера) пользователь может запускать браузер с несколькими вкладками (таким образом, потребляя память - предположим, что это первый вариант для OOMK) , плюс несколько других приложений (текстовый редактор с несохраненными данными, почтовый клиент, программа для чтения PDF-файлов, медиаплеер, ...), плюс несколько (системных) демонов, плюс несколько экземпляров файлового менеджера. Теперь происходит ошибка OOM, и OOMK решает убить браузер, пока пользователь делает что-то, что считается «важным» в сети ... пользователь будет разочарован. С другой стороны, закрытие нескольких экземпляров файлового менеджера, находящихся в режиме ожидания, может освободить точный объем памяти, необходимый, при этом система будет не только работать, но и работать более надежно.
В любом случае, я считаю, что пользователь должен иметь возможность самостоятельно принимать решение о том, что ему делать. В настольной (= интерактивной) системе это должно быть относительно легко сделать при условии, что зарезервировано достаточно ресурсов, чтобы попросить пользователя закрыть любое приложение (но даже закрытия нескольких вкладок может быть достаточно) и выполнить его выбор (вариант может состоят в создании дополнительного файла подкачки, если места достаточно). Что касается сервисов (и в целом), я бы также рассмотрел два дополнительных возможных улучшения: во-первых, регистрируются интервенции OOM-убийцы, а также процессы, запускающие / вызывающие сбои таким образом, чтобы сбой можно было легко отладить (например, API мог сообщить процессу, запускающему создание или разветвление нового процесса - таким образом, такой сервер, как Apache, с надлежащим патчем, может обеспечить лучшую регистрацию определенных ошибок); это может быть сделано независимо от чрезмерной нагрузки / OOMK; во-вторых, но не по важности, можно было бы создать механизм для точной настройки алгоритма OOMK - я знаю, что до некоторой степени можно определить конкретную политику для каждого процесса, но я бы хотел механизм «централизованной» конфигурации, основанный на одном или нескольких списках имен приложений (или идентификаторов) для идентификации соответствующих процессов и придания им определенной степени важности (согласно перечисленным атрибутам); такой механизм должен (или, по крайней мере, мог бы) быть многоуровневым, чтобы мог существовать определяемый пользователем список верхнего уровня, определяемый системой (распределением) список и (нижний уровень) определяемые приложением записи (так , например, файловый менеджер DE мог бы проинструктировать OOMK безопасно уничтожить любой экземпляр, поскольку пользователь может безопасно повторно открыть его для доступа к просмотру потерянного файла, тогда как любая важная операция, такая как перемещение / копирование / создание данных, может быть делегирована более «привилегированный» процесс).
Более того, может быть предоставлен API, позволяющий приложениям повышать или понижать уровень своей «важности» во время выполнения (в отношении целей управления памятью и независимо от приоритета выполнения), так что, например, процессор Word может запускаться с низкая `` важность '', но повышается, поскольку некоторые данные хранятся перед сбросом в файл или выполняется операция записи, и снова понижается важность, когда такая операция завершается (аналогично, файловый менеджер может изменить уровень, когда он перешел из использование файлов для работы с данными и наоборот, вместо использования отдельных процессов, и Apache может давать разные уровни важности разным дочерним элементам или изменять дочернее состояние в соответствии с некоторой политикой, определяемой системными администраторами и предоставляемой через Apache - или любой другой тип сервера. - настройки). Конечно, таким API могли и будут злоупотреблять / неправильно использовать, но я думаю, что это незначительная проблема по сравнению с ядром, произвольно уничтожающим процессы для освобождения памяти без какой-либо соответствующей информации о том, что происходит в системе (и потреблении памяти / времени создания или то же самое для меня недостаточно актуально или `` проверяет '') - только пользователи, администраторы и авторы программ могут действительно определить, `` все еще нужен '' процесс по какой-либо причине, в чем причина и / или находится ли приложение в состояние, приводящее к потере данных или другим повреждениям / проблемам в случае гибели; однако можно сделать некоторые предположения, например, поиск ресурсов определенного типа (файловые дескрипторы, сетевые сокеты и т. д.), полученных процессом, и с ожидающими операциями, может определить, должен ли процесс находиться в более высоком «состоянии», чем один набор, или если его `` самоустановленный '' один выше, чем необходимо, и может быть снижен (агрессивный подход, если он не заменяется выбором пользователя, например, принуждение к определенному состоянию или просьба - через списки, которые я упомянул выше - уважать выбор приложения).
Или просто избегайте чрезмерной загрузки и позвольте ядру делать именно то, что должно делать ядро: выделять ресурсы (но не спасать их произвольно, как это делает убийца OOM), планировать процессы, предотвращать голодание и взаимоблокировки (или спасаться от них), обеспечивать полное вытеснение и разделение пространств памяти и так далее ...
Я бы также потратил еще несколько слов на подходы с чрезмерной нагрузкой. Из других обсуждений я пришел к выводу, что одна из основных проблем, связанных с чрезмерной фиксацией (как причина желать этого, так и как источник возможных проблем), заключается в обработке вилок: честно говоря, я не знаю, как именно копировать- Реализована стратегия при записи, но я думаю, что любая агрессивная (или оптимистичная) политика может быть смягчена стратегией, подобной обмену местностью. То есть вместо простого клонирования (и настройки) разветвленных кодовых страниц процесса и структур планирования можно было бы скопировать несколько других страниц данных перед фактической записью, выбирая среди тех страниц, к которым родительский процесс обращался для записи чаще (т. Е. с использованием счетчика для операций записи).
Все, конечно, ИМХО.
Если ваша память полностью израсходована процессами до такой степени, что это может угрожать стабильности системы, тогда появляется убийца OOM. Задача OOM Killer - остановить процессы до тех пор, пока не будет освобождено достаточно памяти для бесперебойного функционирования остальной части процесса. Убийца OOM должен выбрать «лучший» процесс для уничтожения. «Лучший» здесь относится к процессу, который освобождает максимум памяти при уничтожении, а также наименее важен для системы. Основная цель - убить наименьшее количество процессов, что минимизирует нанесенный ущерб и в то же время максимизирует объем освобожденной памяти. Чтобы облегчить это, ядро поддерживает oom_score для каждого из процессов. Вы можете увидеть oom_score каждого из процессов в файловой системе / proc в каталоге pid
# cat /proc/10292/oom_score
Чем выше значение oom_score для любого процесса, тем выше вероятность его уничтожения OOM Killer в случае нехватки памяти.
Кредит: - Ядро Linux запускает убийцу OOM