Как может быть сценарий OOM в Linux (эвристика, стоящая за убийцей OOM)?
Я в курсе концепции виртуальной памяти. А с помощью подкачки по требованию (в зависимости от vm.overcommit_memory) вы можете выделить больше памяти, чем доступно ОЗУ. Пока вы не "дотронетесь" до страницы, на самом деле ничего не произойдет. Иначе, я предполагаю, что имеется ошибка страницы, и тогда для фрейма страницы используется физическая память. Но это каким-то образом подразумевает, что если система нехватает памяти, она просто выгрузит последние использованные материалы и будет работать нормально.
Как может возникнуть необходимость убить процесс? Это происходит потому, что слишком много памяти mlock()- ред. OOM вызывается после того, как слишком много мусора? Или по-другому спросить: какие именно эвристики стоят за активацией OOM-убийцы?
Я читал, что вы можете сделать "echo 1 > memory.oom_control" или "echo -17 > /proc/PID/oom_adj", чтобы отключить его. Каковы последствия этого? Машина, вероятно, на некоторое время перестанет отвечать на запросы. Но если каким-то образом нарушающий процесс обнаруживает, что он не прогрессирует, он также может временно прекратить потребление памяти (так быстро), и в конечном итоге все должно начать работать снова, или я ошибаюсь?
В моем сценарии есть только один процесс (который имеет огромный кэш в памяти). Эти данные, конечно, не являются постоянными, но я бы все же не перезапустил процесс (и перезагрузил эти данные).
1 ответ
Вы, похоже, не понимаете, как связаны виртуальная память и чрезмерная загрузка.
Физическая память состоит из микросхем оперативной памяти вашего компьютера. Физически невозможно одновременно использовать больше памяти, чем у вас есть физическая память. Однако с конца 1970-х годов существует виртуальная память, в которой система перемещает некоторые данные из физической памяти на диск, тем самым сохраняя память, которая фактически не используется, поэтому физическая память может использоваться для других целей. Когда это происходит, программы не могут сразу использовать данные, которые были выгружены; в любом случае, когда они пытаются это сделать, процессор генерирует ошибку страницы, в результате чего операционная система загружает необходимые данные из раздела подкачки обратно в физическую память.
Используя виртуальную память, общий объем данных в полете, которые могут использоваться, увеличивается до размера физической памяти плюс пространство подкачки. Хотя это позволяет системе запускать больше программ одновременно, объем фактически используемой памяти никогда не может превышать общий объем доступной виртуальной памяти (т. Е. ОЗУ + пространство подкачки)
В принципе, ядро должно отслеживать объем памяти, запрашиваемый у него программами, и отклонять запросы на выделение дополнительной памяти, как только его бухгалтерия сообщает ему, что вся память выделена, хотя не вся она могла бытьиспользована., Большинство других ядер делают это, и поэтому у них нет убийцы OOM (потому что им это не нужно).
Однако системный вызов программы для выделения памяти из ядра не выделяет память байтом; он выделяет его большими блоками. Напротив, фактическая реализация, используемая большинством программ для получения памяти (malloc()
Функция библиотеки C) позволяет программам выделять память байтом. Это означает, что большинство программ, когда они просят немного памяти, в конечном итоге malloc()
выделять больше, чем им действительно нужно. Кроме того, хороший malloc()
Реализация будет использовать некоторую эвристику для разделения меньших и больших выделений, так что фрагментация памяти не так уж плоха, но для этого требуется запросить больше памяти у ядра, что усугубит проблему. В результате этих и других эффектов без чрезмерной загрузки будут выделяться большие объемы памяти, но они никогда не будут использоваться.
Идея чрезмерной загрузки состоит в том, что вы можете безопасно выделить немного больше памяти, чем общий объем виртуальной памяти, доступной вашей системе, без ее обратной нагрузки. По сути, ядро утверждает, что оно разрешает распределение, даже если оно знает, что оно не может выполнить это обещание, при условии, что оно не должно будет полностью выполнять эти обещания. Однако точную сумму, которая может быть чрезмерно распределена - распределена - без каких-либо проблем, невозможно предсказать; поэтому, когда ядро обнаружит, что программы пытаются использовать всю выделенную им память, ядру придется выполнить свои обещания. Вот где приходит убийца ООМ.
Является ли это хорошей идеей, подлежит обсуждению. Когда системе не хватает памяти, что-то пойдет не так. Если это случай, когда какое-то приложение пытается выделить больше памяти, но ядро уже зарезервировало все, то, возможно, это конкретное приложение будет аварийно завершено. Если это просто ваш X-сервер, вам не повезло. По крайней мере, если есть убийца OOM, он может решить, какой процесс убить, а не дела идут плохо после плохого распределения; и убийца OOM имеет некоторую логику, чтобы избежать уничтожения важных процессов, таких как ваш X-сервер...
Однако, если вы предпочитаете, есть некоторые ручки sysctl, которые вы можете использовать, чтобы отключить чрезмерную загрузку, если вы думаете, что это плохая идея.