Como vm.overcommit_memory funciona?

50

Quando uso as configurações padrão:

vm.overcommit_memory = 0
vm.overcommit_ratio = 50

Eu posso ler esses valores do /proc/meminfoarquivo:

CommitLimit:     2609604 kB
Committed_AS:    1579976 kB

Mas quando mudo vm.overcommit_memoryde 0para 2, não consigo iniciar o mesmo conjunto de aplicativos que eu poderia iniciar antes da alteração, especialmente o amarok. Eu tive que mudar vm.overcommit_ratiopara 300, para que o limite pudesse ser aumentado. Agora, quando inicio o amarok, /proc/meminfomostra o seguinte:

CommitLimit:     5171884 kB
Committed_AS:    3929668 kB

Esta máquina possui apenas 1GiB de RAM, mas o amarok funciona sem problemas quando vm.overcommit_memoryé definido como 0. Mas, no caso de configurá-lo como 2, o amarok precisa alocar mais de 2GiB de memória. É um comportamento normal? Se sim, alguém poderia explicar por que, por exemplo, o Firefox (que consome 4-6x mais memória que o amarok) funciona da mesma maneira antes e depois da alteração?

Mikhail Morfikov
fonte

Respostas:

67

Você pode encontrar a documentação em man 5 proc( ou no 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

A resposta simples é que a configuração de confirmação excessiva para 1 definirá o cenário para que, quando um programa chame algo como malloc()alocar um pedaço de memória ( man 3 malloc), ele sempre tenha êxito, independentemente do sistema saber que não terá toda a memória que está sendo usada. pediu.

O conceito subjacente a entender é a idéia de memória virtual . Os programas veem um espaço de endereço virtual que pode ou não ser mapeado para a memória física real. Ao desativar a verificação de supercomprometimento, você instrui o sistema operacional a assumir que sempre há memória física suficiente para fazer backup do espaço virtual.

Exemplo

Para destacar por que isso às vezes importa, dê uma olhada nas orientações do Redis sobre por que vm.overcommit_memorydeve ser definido como 1 para isso.

Kyle Brandt
fonte
2
Mas o valor de não deveria Committed_ASser o mesmo nos dois casos?
Mikhail Morfikov
@MikhailMorfikov: Em teoria, acredito que sim, mas quem sabe o que esses programas estão fazendo? Gostaria de ver um ambiente mais controlado com um programa simples que apenas aloca digamos um show de ram via Malloc. E, em seguida, execute o teste após reiniciar entre os testes.
Kyle Brandt
Ok, então eu vou ficar 0por agora.
Mikhail Morfikov
2
@MikhailMorfikov: Sim, praticamente acho que 0 faz mais sentido. No meu ambiente, a única vez em que habilito 1 é para Redis, que faz coisas nas quais espera , solicitando muito mais memória que está usando devido a um fork (). A criança usará praticamente todas as mesmas páginas de memória, mas o Linux não sabe que isso é seguro, mas deve assumir que será usada 2x memória (se você quiser saber mais: redis.io/topics/faq )
Kyle Brandt
a última afirmação em sua resposta não deve começar como "ativando a confirmação excessiva"? porque defini-lo como 1 significa que você está pedindo demais, certo?
asgs