38 votos

¿Desactivar por defecto el OOM killer de Linux?

El asesino OOM en Linux causa estragos en varias aplicaciones de vez en cuando, y parece que no se hace mucho en el lado del desarrollo del kernel para mejorar esto. ¿No sería mejor, como mejor práctica al configurar un nuevo servidor para invertir el valor por defecto de la sobrecarga de memoria, es decir, desactivarla ( vm.overcommit_memory=2 ) a menos que sepas que lo quieres encendido para tu uso particular? ¿Y cuáles serían esos casos de uso en los que sabe que quiere activar el overcommitting?

Como ventaja, ya que el comportamiento en caso de vm.overcommit_memory=2 depende de vm.overcommit_ratio y espacio de intercambio, ¿cuál sería una buena regla general para dimensionar los dos últimos de modo que toda esta configuración siga funcionando razonablemente?

67voto

noocyte Puntos 150

Una analogía interesante (de http://lwn.net/Articles/104179/ ):

Una empresa aeronáutica descubrió que era más barato volar sus aviones con menos combustible a bordo. Los aviones serían más ligeros y consumirían menos combustible. dinero. Sin embargo, en raras ocasiones la cantidad de combustible era insuficiente, y el avión se estrellaba. Este problema de problema fue resuelto por los ingenieros de la compañía mediante el desarrollo de un mecanismo especial OOF (out-of-fuel). En caso de emergencia, un pasajero seleccionado y expulsado del avión. (Si era necesario, se repetía el procedimiento). repetía el procedimiento). Se elaboró un amplio corpus teórico y se dedicaron muchas publicaciones publicaciones sobre el problema de seleccionar correctamente a la víctima a expulsar. ¿Debe elegirse al azar? ¿O se debe elegir a la persona más pesada? ¿O a la de más edad? ¿Deben pagar los pasajeros de pasajeros pagar para no ser expulsados, de modo que la víctima sería el más pobre a bordo? Y si por por ejemplo, se eligiera a la persona elegida, ¿debería haber una excepción en caso de que fuera el piloto? ¿Los pasajeros de primera clase exentos? Ahora que el mecanismo OOF existía, se activaría cada vez en cuando, y expulsaría a los pasajeros incluso cuando no hubiera escasez de combustible. Los ingenieros todavía están estudiando precisamente cómo este mal funcionamiento causa.

12 votos

Me ha gustado mucho, gracias por desenterrarlo.

34voto

Ryan Sampson Puntos 2898

El asesino OOM sólo causa estragos si has sobrecargado el sistema. Dale suficiente swap y no ejecutes aplicaciones que de repente decidan consumir cantidades masivas de RAM, y no tendrás problemas.

Para responder específicamente a sus preguntas:

  • No creo que sea una buena idea desactivar overcommit en el caso general; muy pocas aplicaciones están escritas para hacer frente adecuadamente a brk (2) (y las envolturas que lo utilizan, como malloc (3)) devuelve un error. Cuando experimenté con esto en mi trabajo anterior, se consideró que era más una molestia conseguir que todo fuera capaz de manejar errores fuera de memoria que simplemente lidiar con las consecuencias de un OOM (que, en nuestro caso, era mucho peor que tener que reiniciar el servicio ocasional si se producía un OOM - teníamos que reiniciar un clúster entero, porque GFS es un montón de heces humeantes).
  • Quieres overcommitting on para cualquier proceso que overcommits memoria. Los dos culpables más comunes aquí son Apache y la JVM, pero muchas aplicaciones hacen esto en mayor o menor grado. Ellos piense en ellos puede necesitan mucha memoria en el futuro, por lo que toman una gran parte de inmediato. En un sistema con overcommit activado, el kernel dice "meh, da igual, ven a molestarme cuando realmente quieras escribir en esas páginas" y no pasa nada malo. En un sistema overcommit-off, el kernel dice "no, no puedes tener tanta memoria, si llegas a escribir en ella en algún momento en el futuro estoy jodido, así que no hay memoria para ti" y la asignación falla. Desde nada por ahí dice "oh, vale, ¿puedo tener esta cantidad más pequeña de segmento de datos de proceso?", entonces el proceso o bien (a) se cierra con un error de falta de memoria, o (b) no comprueba el código de retorno de malloc, piensa que está bien y escribe en una posición de memoria inválida, causando un segfault. Afortunadamente, la JVM hace todas sus preasignaciones al arrancar (así que la JVM arranca o muere inmediatamente, lo que normalmente se nota), pero Apache hace sus cosas raras con cada nuevo hijo, lo que puede tener efectos excitantes en producción (excitaciones irreproducibles del tipo "no manejar conexiones").
  • No me gustaría establecer mi overcommit_ratio más alto que el predeterminado del 50%. De nuevo, según mis pruebas, aunque establecerlo alrededor de 80 o 90 podría sonido Aunque es una buena idea, el kernel necesita grandes cantidades de memoria en momentos inoportunos, y un sistema totalmente cargado con un alto ratio de sobrecompromiso es probable que no disponga de suficiente memoria libre cuando el kernel la necesite (lo que provoca miedo, pestilencia y oopses). Así que jugar con el sobrecompromiso introduce un nuevo y aún más divertido modo de fallo: en lugar de simplemente reiniciar cualquier proceso que se haya quedado sin OOM cuando te quedas sin memoria, ahora tu máquina se bloquea, provocando un apagón de todo lo que hay en la máquina. ¡INCREÍBLE!
  • El espacio de intercambio en un sistema sin sobrecompromisos depende de la cantidad de memoria solicitada pero no utilizada que necesiten las aplicaciones, además de un buen margen de seguridad. El lector puede calcular lo que necesita en cada caso concreto.

Básicamente, mi experiencia es que desactivar el overcommit es un bonito experimento que rara vez funciona tan bien en la práctica como parece en teoría. Esto se corresponde muy bien con mis experiencias con otros sintonizables en el kernel -- los desarrolladores del kernel de Linux son casi siempre más inteligentes que tú, y los valores por defecto funcionan mejor para la gran mayoría, vasto mayoría de los casos. Déjelos en paz y, en su lugar, busque qué proceso tiene la fuga y arréglelo.

3 votos

No quiero que mi proceso de copia de seguridad sea asesinado porque alguien está DoS-ing mi servidor web. Las excepciones están bien, pero el valor por defecto debe ser la seguridad y la coherencia. Optimizaciones como OOM deberían ser activadas manualmente IMHO. Es como codificar, codificas limpiamente, y luego optimizas. Over-commit es una buena característica, pero no debería ser la opción por defecto.

1 votos

Si no quieres que tu proceso de copia de seguridad muera porque alguien está haciendo DoS a tu servidor web, no configures tu servidor web de tal manera que un DoS pueda causar que los recursos del sistema se saturen.

0 votos

Tengo 8GB de RAM y simplemente ejecutando Firefox y una máquina virtual a veces resulta en el OOM killer matando la VM. Compilando Unreal Engine 4, cada invocación clang toma 1~1.5GB de memoria y de nuevo, el OOM killer mata una de vez en cuando. Ahora estoy generalmente bien con eso, sin el asesino OOM probablemente segfault de todos modos. Es sólo que cada vez que OOM killer quiere matar un proceso, mi sistema se congela durante 10 minutos antes de que el proceso malo sea realmente matado. ¿Bug quizás? Lo más probable. ¿Lo quiero? Definitivamente no. Y esa es la razón por la que uno podría querer desactivar el OOM killer.

7voto

Hmm, no me convencen del todo los argumentos a favor de overcommit y OOM killer... Cuando womble escribe,

"El asesino OOM sólo causa estragos si has sobrecargado tu sistema. Dale suficiente swap y no ejecutes aplicaciones que de repente decidan comerse cantidades ingentes de RAM, y no tendrás problemas".

Se trata de describir un escenario de entorno en el que el overcommit y el OOM killer no se aplican, o no actúan "realmente" (si todas las aplicaciones asignaran memoria según la necesitaran, y hubiera suficiente memoria virtual para asignar, las escrituras de memoria seguirían de cerca las asignaciones de memoria sin errores, por lo que no podríamos hablar realmente de un sistema overcommited aunque se activara una estrategia overcommit). Eso es más o menos una admisión implícita de que el overcommit y el OOM killer funcionan mejor cuando su intervención no es necesaria, lo que de alguna manera comparten la mayoría de los partidarios de esta estrategia, por lo que puedo decir (y admito que no puedo decir mucho...). Por otra parte, referirse a aplicaciones con comportamientos específicos a la hora de preasignar memoria me hace pensar que un manejo específico podría ser ajustado a nivel de distribución, en lugar de tener un enfoque por defecto basado en heurísticas (personalmente, creo que la heurística no es un enfoque muy bueno para cosas del kernel).

Por lo que respecta a la JVM, bueno, es una máquina virtual, hasta cierto punto necesita asignar todos los recursos que necesita en el arranque, para que pueda crear su entorno "falso" para sus aplicaciones, y mantener sus recursos disponibles separados del entorno del host, en la medida de lo posible. Por lo tanto, puede ser preferible que falle en el arranque, en lugar de después de un tiempo como consecuencia de una condición OOM 'externa' (causada por overcommit/OOM killer/lo que sea), o de todos modos sufriendo por tal condición que interfiere con sus propias estrategias internas de manejo de OOM (en general, una VM debería obtener cualquier recurso requerido desde el principio y el sistema anfitrión debería 'ignorarlos' hasta el final, de la misma manera que cualquier cantidad de ram física compartida con una tarjeta gráfica nunca es -y no puede ser- tocada por el SO).

Sobre Apache, dudo que tener todo el servidor ocasionalmente muerto y reiniciado sea mejor que dejar que un único hijo, junto con una única conexión, falle desde su (= del hijo/de la conexión) comienzo (como si fuera una instancia completamente nueva de la JVM creada después de que otra instancia funcionara durante un tiempo). Supongo que la mejor "solución" podría depender de un contexto específico. Por ejemplo, considerando un servicio de comercio electrónico, podría ser preferible tener, a veces, unas pocas conexiones a la cesta de la compra fallando aleatoriamente en lugar de perder todo el servicio, con el riesgo, por ejemplo, de interrumpir la finalización de un pedido en curso, o (tal vez peor) un proceso de pago, con todas las consecuencias del caso (tal vez inofensivo, pero tal vez perjudicial - y con seguridad, cuando surgieran problemas, estos serían peores que una condición de error irreproducible para fines de depuración).

De la misma manera, en una estación de trabajo, el proceso que consume más recursos, y por lo tanto la primera opción para el OOM killer, podría ser una aplicación intensiva en memoria, como un transcodificador de vídeo, o un software de renderizado, probablemente la única aplicación que el usuario quiere que no sea tocada. Estas consideraciones me sugieren que la política por defecto del OOM killer es demasiado agresiva. Utiliza un enfoque de "peor ajuste" que es de alguna manera similar al de algunos sistemas de ficheros (el OOMK intenta liberar tanta memoria como puede, mientras reduce el número de subprocesos muertos, con el fin de prevenir cualquier otra intervención en poco tiempo, así como un fs puede asignar más espacio en disco del realmente necesario para un determinado fichero, para prevenir cualquier otra asignación si el fichero crece y así prevenir la fragmentación, hasta cierto punto).

Sin embargo, creo que una política opuesta, como un enfoque de "mejor ajuste", podría ser preferible, para liberar la memoria exacta que se necesita en un momento determinado, y no molestarse con procesos "grandes", que bien podrían estar desperdiciando memoria, pero también podrían no estarlo, y el núcleo no puede saberlo (hmm, Puedo imaginar que mantener un registro de los accesos a las páginas y el tiempo podría indicar si un proceso está asignando memoria que ya no necesita, para adivinar si un proceso está malgastando memoria o simplemente usando mucha, pero los retrasos en los accesos deberían ser ponderados en ciclos de cpu para distinguir entre un malgasto de memoria y una pérdida de memoria. y aplicación intensiva en cpu, pero, aunque potencialmente inexacta, una heurística de este tipo podría tener una sobrecarga excesiva).

Además, puede que no sea cierto que matar el menor número posible de procesos sea siempre una buena elección. Por ejemplo, en un entorno de escritorio (pensemos en un nettop o un netbook con recursos limitados, por ejemplo) un usuario puede estar ejecutando un navegador con varias pestañas (por lo tanto, consume memoria - supongamos que esta es la primera opción para el OOMK), además de algunas otras aplicaciones (un procesador de textos con datos no guardados, un cliente de correo, un lector de pdf, un reproductor multimedia, ...), además de algunos demonios (del sistema), además de algunas instancias del gestor de archivos. Ahora, ocurre un error OOM, y el OOMK elige matar el navegador mientras el usuario está haciendo algo considerado 'importante' en la red... el usuario se decepcionaría. Por otro lado, cerrar las pocas instancias del gestor de archivos que están en reposo podría liberar la cantidad exacta de memoria necesaria y mantener el sistema no sólo funcionando, sino funcionando de una manera más fiable.

De todos modos, creo que el usuario debería poder decidir por sí mismo qué hacer. En un sistema de escritorio (=interactivo), eso debería ser relativamente fácil de hacer, siempre que se reserven recursos suficientes para pedir al usuario que cierre cualquier aplicación (pero incluso cerrar unas cuantas pestañas podría ser suficiente) y se ocupe de su elección (una opción podría consistir en crear un archivo de intercambio adicional, si hay espacio suficiente). Para los servicios (y en general), también consideraría otras dos posibles mejoras: una es el registro de los OOM killer intervents, así como de los procesos que se inician o bifurcan de tal manera que el fallo pueda ser fácilmente depurado (por ejemplo, una API podría informar al proceso que emite la creación de un nuevo proceso o bifurcación - así, un servidor como Apache, con un parche adecuado, podría proporcionar un mejor registro de ciertos errores); esto podría hacerse independientemente del overcommit/OOMK que se esté produciendo; en segundo lugar, pero no por importancia, se podría establecer un mecanismo para afinar el algoritmo OOMK - sé que es posible, hasta cierto punto, definir una política específica proceso por proceso, pero yo apuntaría a un mecanismo de configuración 'centralizado', basado en una o más listas de nombres de aplicaciones (o ids) para identificar procesos relevantes y darles un cierto grado de importancia (según los atributos listados); Tal mecanismo debería (o al menos podría) ser estratificado, de modo que podría haber una lista de alto nivel definida por el usuario, una lista definida por el sistema (distribución), y entradas definidas por la aplicación (de bajo nivel) (así, por ejemplo, un gestor de archivos DE podría instruir al OOMK para matar de forma segura cualquier instancia, ya que un usuario puede reabrirla de forma segura para acceder a la vista del archivo perdido - mientras que cualquier operación importante, como mover/copiar/crear datos podría ser delegada a un proceso más "privilegiado").

Además, se podría proporcionar una API que permitiera a las aplicaciones subir o bajar su nivel de "importancia" en tiempo de ejecución (con respecto a la gestión de la memoria e independientemente de la prioridad de ejecución), de forma que, por ejemplo, un procesador de texto pudiera empezar con una "importancia" baja, pero subirla a medida que se guardan algunos datos antes de volcarlos a un fichero, o se realiza una operación de escritura, y volver a bajar la importancia una vez que dicha operación termine (análogamente, un gestor de ficheros podría cambiar de nivel cuando pasara de sólo leer ficheros a tratar con datos y viceversa, en lugar de usar procesos separados, y Apache podría dar diferentes niveles de importancia a diferentes hijos, o cambiar el estado de un hijo de acuerdo con alguna política decidida por los administradores del sistema y expuesta a través de la configuración de Apache - o de cualquier otro tipo de servidor). Por supuesto, tal API podría y sería abusada/mal usada, pero creo que es una preocupación menor comparada con el kernel matando procesos arbitrariamente para liberar memoria sin ninguna información relevante sobre lo que está pasando en el sistema (y el consumo de memoria/tiempo de creación o similares no son lo suficientemente relevantes o "validadores" para mí) - sólo los usuarios, administradores y escritores de programas pueden realmente determinar si un proceso es "todavía necesario" por alguna razón, cuál es la razón, y/o si la aplicación está en un estado que lleva a la pérdida de datos u otros daños/problemas si se mata; Sin embargo, se podrían hacer algunas suposiciones, por ejemplo, buscar recursos de cierto tipo (descriptores de archivo, sockets de red, etc.) adquiridos por un proceso y con recursos pendientes. ) adquiridos por un proceso y con operaciones pendientes podría decir si un proceso debería estar en un "estado" superior al establecido, o si su estado "autoestablecido" es superior al necesario y puede ser reducido (enfoque agresivo, a menos que sea sustituido por elecciones del usuario, como forzar un cierto estado, o pedir - a través de las listas que he mencionado antes - que se respeten las elecciones de la aplicación).

O, simplemente, evitar el overcommitting y dejar que el kernel haga justo lo que un kernel debe hacer, asignar recursos (pero no rescatarlos arbitrariamente como hace el OOM killer), programar procesos, prevenir starvations y deadlocks (o rescatarlos de ellos), asegurar el preemption completo y la separación de espacios de memoria, etc...

También dedicaría algunas palabras más a los planteamientos de compromiso excesivo. De otras discusiones he sacado la idea de que una de las principales preocupaciones sobre overcommit (tanto como razón para quererlo como fuente de posibles problemas) consiste en el manejo de forks: honestamente, no sé cómo se implementa exactamente la estrategia copy-on-write, pero creo que cualquier política agresiva (u optimista) podría mitigarse con una estrategia de localidad similar a swap. Es decir, en lugar de simplemente clonar (y ajustar) las páginas de código y las estructuras de programación de un proceso bifurcado, se podrían copiar algunas otras páginas de datos antes de una escritura real, eligiendo entre aquellas páginas a las que el proceso padre ha accedido para escribir con más frecuencia (es decir, usando un contador para las operaciones de escritura).

Todo, por supuesto, IMHO.

2voto

Guillaume Algis Puntos 3261

Si su memoria es exhaustivamente utilizada por los procesos hasta el punto que puede amenazar la estabilidad del sistema, entonces el asesino OOM entra en escena. Es tarea del OOM Killer matar los procesos hasta que se libere suficiente memoria para el buen funcionamiento del resto del proceso. El OOM Killer tiene que seleccionar el "mejor" proceso para matar. "Mejor" aquí se refiere a aquel proceso que liberará el máximo de memoria al ser eliminado y que además es el menos importante para el sistema. El objetivo principal es matar el menor número de procesos que minimicen el daño causado y al mismo tiempo maximizar la cantidad de memoria liberada. Para facilitar esto, el kernel mantiene oom_score para cada uno de los procesos. Puedes ver el oom_score de cada uno de los procesos en el sistema de archivos /proc bajo el directorio pid

# cat /proc/10292/oom_score

Cuanto mayor sea el valor de oom_score de cualquier proceso, mayor será su probabilidad de ser eliminado por el OOM Killer en una situación de falta de memoria.

Crédito:- El núcleo de Linux está iniciando el asesino OOM

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X