¿Cómo funciona vm.overcommit_memory?

50

Cuando uso la configuración predeterminada:

vm.overcommit_memory = 0
vm.overcommit_ratio = 50

Puedo leer estos valores del /proc/meminfoarchivo:

CommitLimit:     2609604 kB
Committed_AS:    1579976 kB

Pero cuando cambio vm.overcommit_memoryde 0a 2, no puedo iniciar el mismo conjunto de aplicaciones que podría iniciar antes del cambio, especialmente amarok. Tuve que cambiarme vm.overcommit_ratiopara 300poder aumentar el límite. Ahora cuando comienzo amarok, /proc/meminfomuestra lo siguiente:

CommitLimit:     5171884 kB
Committed_AS:    3929668 kB

Esta máquina tiene solo 1GiB de RAM, pero amarok funciona sin problemas cuando vm.overcommit_memoryse establece en 0. Pero en el caso de configurarlo 2, amarok necesita asignar más de 2GiB de memoria. ¿Es un comportamiento normal? Si es así, ¿alguien podría explicar por qué, por ejemplo, Firefox (que consume 4-6 veces más memoria que amarok) funciona de la misma manera antes y después del cambio?

Mikhail Morfikov
fuente

Respuestas:

67

Puede encontrar la documentación en man 5 proc( o en kernel.org ):

/proc/sys/vm/overcommit_memory
       This file contains the kernel virtual memory accounting mode.
       Values are:

              0: heuristic overcommit (this is the default)
              1: always overcommit, never check
              2: always check, never overcommit

       In mode 0, calls of mmap(2) with MAP_NORESERVE are not
       checked, and the default check is very weak, leading to the
       risk of getting a process "OOM-killed".

       In mode 2 (available since Linux 2.6), the total virtual
       address space that can be allocated (CommitLimit in /proc/mem‐
       info) is calculated as

           CommitLimit = (total_RAM - total_huge_TLB) *
                         overcommit_ratio / 100 + total_swap

La respuesta simple es que la configuración de sobrecompromiso en 1, establecerá el escenario para que cuando un programa llame a algo como malloc()asignar un trozo de memoria ( man 3 malloc), siempre tendrá éxito independientemente de si el sistema sabe que no tendrá toda la memoria que está siendo pedido

El concepto subyacente a entender es la idea de la memoria virtual . Los programas ven un espacio de dirección virtual que puede, o no, asignarse a la memoria física real. Al deshabilitar la comprobación de sobrecompromiso, le dice al sistema operativo que asuma que siempre hay suficiente memoria física para respaldar el espacio virtual.

Ejemplo

Para resaltar por qué esto a veces puede importar, eche un vistazo a las guías de Redis sobre por qué vm.overcommit_memorydebería establecerse en 1 para ello.

Kyle Brandt
fuente
2
Pero, ¿no debería Committed_ASser el mismo valor en ambos casos?
Mikhail Morfikov
@MikhailMorfikov: En teoría, creo que sí, pero quién sabe qué están haciendo estos programas. Me gustaría ver un entorno más controlado con un programa simple que solo asigna, por ejemplo, un concierto de ram a través de Malloc. Y luego ejecute la prueba después de reiniciar entre pruebas.
Kyle Brandt
Ok, entonces me quedaré con ellos 0por ahora.
Mikhail Morfikov
2
@MikhailMorfikov: Sí, prácticamente creo que 0 tiene más sentido. En mi entorno, la única vez que habilito 1 es para Redis, que hace cosas donde espera pedir mucha más memoria que está usando debido a una bifurcación (). El niño usará las mismas páginas de memoria, pero Linux no sabe que para estar seguro tiene que asumir que se usará 2x de memoria (si desea obtener más información: redis.io/topics/faq )
Kyle Brandt
¿No debería comenzar la última declaración en su respuesta como "habilitando sobrecompromiso"? porque establecerlo en 1 significa que le está pidiendo que se comprometa de más, ¿verdad?
pide el