El asesino de OOM en Linux causa estragos en varias aplicaciones de vez en cuando, y parece que realmente no se hace mucho en el lado del desarrollo del kernel para mejorar esto. ¿No sería mejor, como práctica recomendada al configurar un nuevo servidor , revertir el valor predeterminado en la sobrecompromiso de memoria, es decir, desactivarlo ( vm.overcommit_memory=2
) a menos que sepa que lo desea para su uso particular? ¿Y cuáles serían esos casos de uso en los que sabes que quieres comprometerte demasiado?
Como beneficio adicional, dado que el comportamiento en caso de vm.overcommit_memory=2
depende del vm.overcommit_ratio
espacio e intercambio, ¿cuál sería una buena regla general para dimensionar los dos últimos para que toda esta configuración siga funcionando razonablemente?
El asesino OOM solo causa estragos si ha sobrecargado su sistema. Intercambie lo suficiente y no ejecute aplicaciones que de repente decidan comer grandes cantidades de RAM, y no tendrá ningún problema.
Para responder específicamente a sus preguntas:
brk
(2) (y los contenedores que lo usan, comomalloc
(3)) devuelven un error. Cuando experimenté con esto en mi trabajo anterior, se consideró que era más complicado conseguir todo lo que fuera capaz de manejar errores de falta de memoria que solo lidiar con las consecuencias de un OOM (que, en nuestro caso, fue mucho peor que tener que reiniciar el servicio ocasional si ocurría una OOM: tuvimos que reiniciar un clúster completo, porque GFS es una pila de heces humeantes).Básicamente, mi experiencia es que desactivar el exceso de compromiso es un buen experimento que rara vez funciona tan bien en la práctica como suena en teoría. Esto se corresponde muy bien con mis experiencias con otros ajustables en el kernel: los desarrolladores del kernel de Linux son casi siempre más inteligentes que usted, y los valores predeterminados funcionan mejor para la gran mayoría de los casos. Déjelos en paz y, en su lugar, busque qué proceso tiene la fuga y arréglelo.
fuente
Hmm, no estoy completamente convencido por los argumentos a favor del exceso de compromiso y el asesino OOM ... Cuando womble escribe,
"El asesino OOM solo causa estragos si has sobrecargado tu sistema. Dale suficiente intercambio y no ejecutes aplicaciones que de repente decidan comer grandes cantidades de RAM, y no tendrás ningún problema".
Se trata de describir un escenario de entorno en el que el sobrecompromiso y el asesino de OOM no se aplican, o no 'realmente' actúan (si todas las aplicaciones asignan memoria según sea necesario, y hubiera suficiente memoria virtual para asignar, las escrituras en memoria seguirían de cerca las asignaciones de memoria sin errores, por lo que realmente no podríamos hablar sobre un sistema sobrecomprometido, incluso si se habilitara una estrategia de sobrecompromiso). Se trata de una admisión implícita de que el exceso de compromiso y el asesino de OOM funcionan mejor cuando no se necesita su intervención, que de alguna manera es compartida por la mayoría de los partidarios de esta estrategia, hasta donde puedo decir (y admito que no puedo decir mucho ...). Además, al referirme a aplicaciones con comportamientos específicos al preasignar memoria me hace pensar que un manejo específico podría ajustarse a un nivel de distribución, en lugar de tener un valor predeterminado,
En lo que concierne a la JVM, bueno, es una máquina virtual, en cierta medida necesita asignar todos los recursos que necesita en el inicio, para que pueda crear su entorno 'falso' para sus aplicaciones y mantener sus recursos disponibles separados del host. entorno, en la medida de lo posible. Por lo tanto, puede ser preferible que falle en el inicio, en lugar de después de un tiempo como consecuencia de una condición OOM 'externa' (causada por un exceso de compromiso / asesino OOM / lo que sea), o de todos modos sufriendo por una condición que interfiere con la suya estrategias de manejo interno de OOM (en general, una VM debe obtener los recursos necesarios desde el principio y el sistema host debe '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 - Tocado por el sistema operativo).
Sobre Apache, dudo que hacer que todo el servidor se apague y reinicie ocasionalmente es mejor que dejar que un solo niño, junto con una sola conexión, falle desde su inicio (= el niño / la conexión) (como si fuera una instancia completamente nueva de la JVM creada después de otra instancia se ejecuta por un tiempo). Supongo que la mejor 'solución' podría depender de un contexto específico. Por ejemplo, teniendo en cuenta un servicio de comercio electrónico, puede ser preferible tener algunas conexiones con el gráfico de compras que fallan al azar 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 dañino, y seguro, cuando surgieron problemas,
Del mismo modo, en una estación de trabajo, el proceso que consume la mayor cantidad de recursos y, por lo tanto, como la primera opción para el asesino de OOM, podría ser una aplicación de uso intensivo de memoria, como un transcodificador de video o un software de representación, probablemente la única aplicación el usuario quiere no ser tocado. Estas consideraciones me insinúan que la política predeterminada del asesino OOM es demasiado agresiva. Utiliza un enfoque de "peor ajuste" que de alguna manera es similar al de algunos sistemas de archivos (el OOMK intenta y libera tanta memoria como puede, al tiempo que reduce el número de subprocesos muertos, para evitar cualquier intervención adicional en poco tiempo, ya que así como un fs puede asignar más espacio en disco del que realmente se necesita para un determinado archivo, para evitar cualquier asignación adicional si el archivo creció y, por lo tanto, previene la fragmentación, hasta cierto punto).
Sin embargo, creo que una política opuesta, como un enfoque de "mejor ajuste", podría ser preferible, por lo que liberar la memoria exacta que se necesita en un momento determinado y no molestar con procesos "grandes", que bien podrían estar desperdiciando memoria, pero también podría no serlo, y el kernel no puede saber eso (hmm, me imagino que mantener un registro del acceso a la página y el tiempo podría sugerir que si un proceso está asignando memoria ya no necesita más, así que adivinar si un proceso está desperdiciando memoria o simplemente está usando mucho, pero los retrasos de acceso deben ser ponderados en los ciclos de CPU para distinguir el desperdicio de memoria de una aplicación intensiva de memoria y CPU, pero, aunque potencialmente inexacto, dicha heurística podría tener una sobrecarga excesiva).
Además, podría no ser cierto que matar la menor cantidad de procesos posibles es siempre una buena elección. Por ejemplo, en un entorno de escritorio (pensemos en una nettop o una netbook con recursos limitados, por ejemplo), un usuario podría estar ejecutando un navegador con varias pestañas (por lo tanto, consume mucha memoria, supongamos que esta es la primera opción para el OOMK) , más algunas otras aplicaciones (un procesador de texto con datos no guardados, un cliente de correo, un lector de pdf, un reproductor multimedia, ...), más algunos demonios (del sistema), más algunas instancias de administrador de archivos. Ahora, ocurre un error OOM, y el OOMK elige matar el navegador mientras el usuario está haciendo algo que se considera 'importante' en la red ... el usuario se decepcionará. Por otro lado, cerrando los pocos administrador de archivos
De todos modos, creo que el usuario debería estar habilitado para tomar una decisión por sí mismo sobre qué hacer. En un sistema de escritorio (= interactivo), eso debería ser relativamente fácil de hacer, siempre que se reserven suficientes recursos para pedirle al usuario que cierre cualquier aplicación (pero incluso cerrar unas pocas pestañas podría ser suficiente) y manejar su elección (una opción podría consiste en crear un archivo de intercambio adicional, si hay suficiente espacio). Para los servicios (y en general), también consideraría otras dos mejoras posibles: una es registrar las intervenciones de OOM killer, así como los procesos que inician / bifurcan fallas de tal manera que la falla se pueda depurar fácilmente (por ejemplo, una API podría informar al proceso que emite la nueva creación o bifurcación del proceso; por lo tanto, un servidor como Apache, con un parche adecuado, podría proporcionar un mejor registro para ciertos errores); esto podría hacerse independientemente si el exceso de compromiso / OOMK está en esfuerzo; en segundo lugar, pero no por importancia, se podría establecer un mecanismo para ajustar el algoritmo OOMK: sé que es posible, hasta cierto punto, definir una política específica proceso por proceso, pero apuntaría a mecanismo de configuración 'centralizado', basado en una o más listas de nombres de aplicaciones (o identificadores) para identificar procesos relevantes y darles un cierto grado de importancia (según los atributos enumerados); dicho mecanismo también debería (o al menos podría) estar en capas, de modo que podría haber una lista definida por el usuario de nivel superior, una lista definida por el sistema (distribución) y entradas definidas por la aplicación (nivel inferior) , por ejemplo, un administrador de archivos DE podría indicarle a OOMK que elimine de forma segura cualquier instancia,
Además, se podría proporcionar una API para permitir que las aplicaciones aumenten o disminuyan su nivel de 'importancia' en tiempo de ejecución (con respecto a los propósitos de administración de memoria e independientemente de la prioridad de ejecución), de modo que, por ejemplo, un procesador de Word pueda comenzar con una 'importancia' baja, pero aumente a medida que se retengan algunos datos antes de pasar a un archivo, o se realice una operación de escritura, y vuelva a tener una importancia menor una vez que dicha operación termine (análogamente, un administrador de archivos podría cambiar el nivel cuando pasa de solo cargar archivos para tratar con datos y viceversa, en lugar de usar procesos separados, y Apache podría dar diferentes niveles de importancia a diferentes niños, o cambiar un estado secundario de acuerdo con alguna política decidida por los administradores de sistemas y expuesta a través de Apache, o cualquier otro tipo de servidor - ajustes). Por supuesto, tal API podría y sería maltratada / mal utilizada, pero creo que es una preocupación menor en comparación con el kernel que mata arbitrariamente los procesos para liberar memoria sin ninguna información relevante sobre lo que está sucediendo en el sistema (y el consumo de memoria / tiempo de creación o similares) es lo suficientemente relevante o 'validar' para mí): solo los usuarios, administradores y escritores de programas realmente pueden determinar si un proceso 'todavía es necesario' por alguna razón, cuál es la razón y / o si la aplicación está en un estado líder a pérdida de datos u otros daños / problemas si se mata; sin embargo, aún podría hacerse alguna suposición, por ejemplo, buscar recursos de un cierto tipo (descriptores de archivo, sockets de red, etc.) adquiridos por un proceso y con operaciones pendientes podría decir si un proceso debería estar en un 'estado' más alto que el conjunto
O simplemente evite comprometerse demasiado y deje que el kernel haga exactamente lo que debe hacer un kernel, asignando recursos (pero no rescatándolos arbitrariamente como lo hace el asesino OOM), programando procesos, previniendo hambrunas y puntos muertos (o rescatando de ellos), asegurando una prevención total y separación de espacios de memoria, etc.
También pasaría algunas palabras más sobre los enfoques de sobrecompromiso. De otras discusiones, he tomado la idea de que una de las principales preocupaciones sobre el exceso de compromiso (tanto como una razón para quererlo como una fuente de posibles problemas) consiste en el manejo de los tenedores: honestamente, no sé exactamente cómo se implementa la estrategia on-write, pero creo que cualquier política agresiva (u optimista) podría mitigarse mediante una estrategia de localidad de intercambio similar. Es decir, en lugar de simplemente clonar (y ajustar) páginas de códigos de proceso bifurcados y estructuras de programación, se podrían copiar algunas otras páginas de datos antes de una escritura real, eligiendo entre esas páginas a las que ha accedido el proceso principal para escribir con más frecuencia (es decir, usando un contador para operaciones de escritura).
Todo, por supuesto, en mi humilde opinión.
fuente
/proc/$PID/oom_adj
./proc/$PID/oom_score_adj
Crédito: - El kernel de Linux está comenzando el asesino OOM
fuente