Si un proceso requiere mucha memoria, el sistema mueve todos los demás procesos al archivo de intercambio. Incluyendo lo que parece, procesos necesarios como el servidor X11 o el terminal.
Entonces, si un proceso sigue asignando sin límite, todo deja de responder, hasta que el OOM-killer mata ese proceso. Mi computadora portátil parece ser especialmente sensible y reacciona extremadamente mal. Acabo de pasar una HORA ENTERA esperando la finalización del proceso durante el cual ni siquiera se podía mover el cursor del mouse.
¿Cómo puede esto ser evitado?
1) Deshabilitar el intercambio => A menudo inicio muchos procesos que luego se vuelven inactivos. Los inactivos deben trasladarse al intercambio.
2) Obtenga un SSD => demasiado caro
3) establezca una memoria máxima ulimit => pero luego falla en caso de que un programa necesite una gran cantidad de memoria razonable. el problema no es que usa demasiado, sino que suprime los otros procesos
4) mantenga programas importantes (X11, bash, kill, top, ...) en la memoria y nunca intercambie esos => ¿se puede hacer esto? ¿cómo? tal vez solo intercambiar programas grandes?
5)
Respuestas:
TL; DR
Corto temporal / respuesta
ulimit -v
, Verificar , y tal vez establezca un límite rígido o suave utilizando laas
opción enlimits.conf
). Esto solía funcionar lo suficientemente bien, pero gracias a la presentación de WebKitgigacage
, muchas aplicaciones gnome ahora esperan espacios de direcciones ilimitados y no se pueden ejecutar.sysctl vm.overcommit_memory
,sysctl vm.overcommit_ratio
pero este método no funcionó para mí.También encontré:
Solución a largo plazo
espere y espere que algunos parches ascendentes entren en núcleos de distribución estables. También esperamos que los proveedores de distribución optimicen mejor los valores predeterminados del kernel y aprovechen mejor los cgroups systemd para priorizar la capacidad de respuesta de la GUI en las ediciones de escritorio.
Algunos parches de interés:
Por lo tanto, no es solo un mal código de espacio de usuario y configuración de distribución / valores predeterminados lo que tiene la culpa: el kernel podría manejar esto mejor.
Comentarios sobre opciones ya consideradas
Se recomienda proporcionar al menos una pequeña partición de intercambio ( ¿Realmente necesitamos intercambio en los sistemas modernos? ). Deshabilitar el intercambio no solo evita el intercambio de páginas no utilizadas, sino que también puede afectar la estrategia de sobrecompromiso heurística predeterminada del núcleo para asignar memoria ( ¿Qué significa la heurística en Overcommit_memory = 0? ), Ya que esa heurística cuenta con páginas de intercambio. Sin intercambio, el exceso de compromiso todavía puede funcionar en los modos heurístico (0) o siempre (1), pero la combinación de ningún intercambio y la estrategia de exceso de compromiso nunca (2) es probablemente una idea terrible. Por lo tanto, en la mayoría de los casos, es probable que ningún intercambio perjudique el rendimiento.
Por ejemplo, piense en un proceso de larga ejecución que inicialmente toca la memoria para el trabajo de una sola vez, pero luego no libera esa memoria y sigue ejecutando el fondo. El núcleo tendrá que usar RAM para eso hasta que finalice el proceso. Sin ningún intercambio, el kernel no puede localizarlo por otra cosa que realmente quiera usar RAM activamente. También piense en cuántos desarrolladores son perezosos y no liberan explícitamente memoria después del uso.
¡Solo se aplica por proceso, y probablemente sea una suposición razonable que un proceso no debería solicitar más memoria de la que tiene físicamente un sistema! Por lo tanto, probablemente sea útil evitar que un proceso loco solitario desencadene una paliza mientras se establece generosamente.
Buena idea, pero esos programas acapararán la memoria que no están usando activamente. Puede ser aceptable si el programa solo solicita una cantidad modesta de memoria.
La versión systemd 232 acaba de agregar algunas opciones que hacen esto posible: creo que uno podría usar 'MemorySwapMax = 0' para evitar que una unidad (servicio) como ssh tenga algo de memoria intercambiada.
Sin embargo, ser capaz de priorizar el acceso a la memoria sería mejor.
Larga explicación
El kernel de Linux está más ajustado para las cargas de trabajo del servidor, por lo que la capacidad de respuesta de la GUI ha sido lamentablemente una preocupación secundaria ... La configuración de administración de memoria del kernel en la edición de escritorio de Ubuntu 16.04 LTS no parecía diferir de las otras ediciones del servidor. Incluso coincide con los valores predeterminados en RHEL / CentOS 7.2 que generalmente se usan como servidor.
OOM, limite e intercambie integridad por capacidad de respuesta
El intercambio de memoria (cuando el conjunto de memoria de trabajo, es decir, las páginas que se leen y escriben en un período de tiempo corto excede la RAM física) siempre bloqueará la E / S de almacenamiento; ninguna herramienta de kernel puede salvar un sistema de esto sin matar un proceso o dos...
Espero que los ajustes de OOM de Linux que se presenten en los núcleos más recientes reconozcan que este conjunto de trabajo excede la situación de la memoria física y mata un proceso. Cuando no es así, ocurre el problema de la paliza. El problema es que, con una gran partición de intercambio, puede parecer que el sistema todavía tiene espacio para la cabeza mientras que el núcleo se compromete alegremente y aún sirve solicitudes de memoria, pero el conjunto de trabajo podría desbordarse, tratando efectivamente de tratar el almacenamiento como si Es RAM.
En los servidores, acepta la penalización de rendimiento de la paliza por un determinado, lento, no perder datos, compensación. En las computadoras de escritorio, la compensación es diferente y los usuarios preferirían un poco de pérdida de datos (sacrificio de proceso) para mantener las cosas receptivas.
Esta fue una buena analogía cómica sobre OOM: oom_pardon, alias no mates mi xlock
Por cierto,
OOMScoreAdjust
es otra opción del sistema para ayudar al peso y evitar los procesos de destrucción de OOM considerados más importantes.reescritura amortiguada
Creo que " Hacer que la reescritura en segundo plano no sea mala " ayudará a evitar algunos problemas en los que un proceso que acapara la RAM provoca otro intercambio (escritura en el disco) y la escritura masiva en el disco detiene cualquier otra cosa que desee IO. No es la causa del problema, pero sí contribuye a la degradación general de la capacidad de respuesta.
limitación de ulimits
Un problema con ulimits es que el límite de contabilidad se aplica al espacio de direcciones de la memoria virtual (lo que implica combinar tanto el espacio físico como el de intercambio). Según
man limits.conf
:Por lo tanto, configurar un ulimit para que se aplique solo al uso de RAM física ya no parece útil. Por lo tanto
parece ser el único sintonizable respetado.
Desafortunadamente, como se detalla más en el ejemplo de WebKit / Gnome, algunas aplicaciones no pueden ejecutarse si la asignación de espacio de direcciones virtuales es limitada.
cgroups debería ayudar en el futuro?
Actualmente, parece engorroso, pero es posible habilitar algunos indicadores de cgroup del núcleo
cgroup_enable=memory swapaccount=1
(por ejemplo, en la configuración de grub) y luego intentar usar el controlador de memoria cgroup para limitar el uso de la memoria.Los cgroups tienen características de límite de memoria más avanzadas que las opciones 'ulimit'. Las notas de CGroup v2 apuntan a intentos de mejorar el funcionamiento de ulimits.
Las opciones de CGroup se pueden configurar mediante las opciones de control de recursos systemd . P.ej:
Otras opciones útiles pueden ser
Estos tienen algunos inconvenientes:
En CGroup v2 , sugieren que
memory.high
debería ser una buena opción para regular y administrar el uso de memoria por parte de un grupo de procesos. Sin embargo, esta cita sugiere que monitorear las situaciones de presión de memoria necesitaba más trabajo (a partir de 2015).Dado que las herramientas de espacio de usuario de systemd y cgroup son complejas, no he encontrado una manera simple de establecer algo apropiado y aprovechar esto aún más. La documentación de cgroup y systemd para Ubuntu no es excelente. El trabajo futuro debería ser para las distribuciones con ediciones de escritorio para aprovechar cgroups y systemd de modo que bajo una alta presión de memoria, ssh y los componentes de X-Server / window manager obtengan mayor prioridad de acceso a CPU, RAM física y IO de almacenamiento, para evitar competir con los procesos intercambio ocupado Las características de prioridad de CPU y E / S del núcleo han existido por un tiempo. Parece que falta acceso prioritario a la RAM física.
Sin embargo, ¡ni siquiera las prioridades de CPU e IO están configuradas adecuadamente! Cuando pude comprobar los límites de cgroup, cpu group, etc., aplicados, por lo que pude ver, Ubuntu no había hecho ninguna priorización predefinida. Por ejemplo, corrí:
Comparé eso con la misma salida para ssh, samba, gdm y nginx. Cosas importantes como la GUI y la consola de administración remota tienen que luchar por igual con todos los demás procesos cuando se produce la agitación.
Ejemplo de límites de memoria que tengo en un sistema de 16 GB de RAM
Quería habilitar la hibernación, así que necesitaba una gran partición de intercambio. Por lo tanto, intentar mitigar con ulimits, etc.
ulimit
Me puse
* hard as 16777216
de/etc/security/limits.d/mem.conf
tal manera que ningún proceso único podría solicitar más memoria de la que es físicamente posible. No evitaré la agitación por completo, pero sin un solo proceso con uso de memoria codicioso, o una pérdida de memoria, puede provocar la agitación. Por ejemplo, he vistognome-contacts
absorber 8GB + de memoria al hacer cosas mundanas como actualizar la lista global de direcciones desde un servidor de intercambio ...Como se ve
ulimit -S -v
, muchas distribuciones tienen este límite rígido y suave establecido como 'ilimitado' dado, en teoría, un proceso podría terminar solicitando mucha memoria pero solo usando activamente un subconjunto, y correr felizmente pensando que se le ha dado, por ejemplo, 24 GB de RAM mientras El sistema solo tiene 16GB. El límite rígido anterior causará que los procesos que pudieron ejecutarse correctamente se cancelen cuando el núcleo niega sus codiciosas solicitudes de memoria especulativa.Sin embargo, también detecta cosas locas como contactos de gnomos y, en lugar de perder la capacidad de respuesta de mi escritorio, aparece el error "no hay suficiente memoria libre":
Complicaciones que configuran ulimit para el espacio de direcciones (memoria virtual)
Desafortunadamente, a algunos desarrolladores les gusta simular que la memoria virtual es un recurso infinito y establecer un límite en la memoria virtual puede dañar algunas aplicaciones. Por ejemplo, WebKit (del que dependen algunas aplicaciones de gnome) agregó una
gigacage
característica de seguridad que intenta asignar cantidades increíbles de memoria virtual y ocurrenFATAL: Could not allocate gigacage memory
errores con un toque descaradoMake sure you have not set a virtual memory limit
. La solución,GIGACAGE_ENABLED=no
renuncia a los beneficios de seguridad, pero del mismo modo, no se permite limitar la asignación de memoria virtual también se renuncia a una característica de seguridad (por ejemplo, control de recursos que puede evitar la denegación de servicio). Irónicamente, entre los desarrolladores de gigacage y gnome, parecen olvidar que limitar la asignación de memoria es en sí mismo un control de seguridad. Y lamentablemente, noté que las aplicaciones gnome que dependen de gigacage no se molestan en solicitar explícitamente un límite superior, por lo que incluso un límite suave rompe las cosas en este caso.Para ser justos, si el núcleo hizo un mejor trabajo al poder negar la asignación de memoria basada en el uso de la memoria residente en lugar de la memoria virtual, fingir que la memoria virtual es ilimitada sería menos peligroso.
exceso de compromiso
Si prefiere que se les niegue el acceso a la memoria a las aplicaciones y desea detener el exceso de compromiso, use los comandos a continuación para probar cómo se comporta su sistema cuando se encuentra bajo una presión de memoria alta.
En mi caso, la relación de compromiso predeterminada era:
Pero solo entra en vigencia cuando se cambia la política para deshabilitar el exceso de compromiso y aplicar la proporción
La relación implicaba que solo se podían asignar 24GB de memoria en general (16GB RAM * 0.5 + 16GB SWAP). Por lo tanto, probablemente nunca vería aparecer OOM, y sería menos probable que los procesos accedan constantemente a la memoria en el intercambio. Pero también es probable que sacrifique la eficiencia general del sistema.
Esto provocará el bloqueo de muchas aplicaciones, dado que es común que los desarrolladores no manejen con gracia el sistema operativo que rechaza una solicitud de asignación de memoria. Cambia el riesgo ocasional de un bloqueo prolongado debido a la paliza (perder todo su trabajo después del restablecimiento completo) a un riesgo más frecuente de que varias aplicaciones se bloqueen. En mis pruebas, no ayudó mucho porque el escritorio se bloqueó cuando el sistema estaba bajo presión de memoria y no podía asignar memoria. Sin embargo, al menos las consolas y SSH todavía funcionaban.
Cómo funciona la memoria de sobrecompromiso de VM tiene más información.
Elegí volver al valor predeterminado para esto,
sudo sysctl -w vm.overcommit_memory=0
dada la pila gráfica de escritorio completo y las aplicaciones en él se bloquean.fuente
but the kernel won't be able to use an overcommit strategy for allocating memory and this will likely hurt performance. Even a smaller swap partition allows this.
¿Hay alguna prueba de esto? Creo que el kernel se compromete