Efeitos da configuração de vm.overcommit_memory

33

Meu servidor web VPS rodando no CentOS 5.4 (kernel 2.6.16.33-xenU do Linux) irregularmente (como uma vez por mês durante algumas semanas) se torna indiferente devido ao kick-out do oom-killer. O monitoramento do servidor mostra que ele normalmente não fica sem memória, apenas de vez em quando.

Eu li alguns blogs que apontam para esta página que discute a configuração do kernel para gerenciar melhor o overcommit usando as seguintes configurações sysctl:

vm.overcommit_memory = 2
vm.overcommit_ratio = 80

Meu entendimento disso (o que pode estar errado, mas não consigo encontrar uma definição canônica para esclarecer) é que isso impede que o kernel aloque excessivamente a memória além do swap + 80% da memória física.

No entanto, também li algumas outras fontes sugerindo que essas configurações não são uma boa ideia - embora os críticos desta abordagem pareçam estar dizendo "não faça coisas para quebrar seu sistema, ao invés de tentar este julgamento" na suposição de que a causação é sempre conhecida.

Então, minha pergunta é, quais são os prós e contras dessa abordagem , no contexto de um servidor da Web Apache2 que hospeda cerca de 10 sites de baixo tráfego? No meu caso específico, o servidor web possui 512Mb de RAM, com 1024Mb de espaço de troca. Isso parece ser adequado para a grande maioria das vezes.

    
por dunxd 22.02.2012 / 11:43

2 respostas

28

A definição de overcommit_ratio a 80 provavelmente não é a ação correta. Definir o valor para algo menor que 100 é quase sempre incorreto.

A razão para isso é que os aplicativos linux alocam mais do que realmente precisam. Digamos que eles aloquem 8kb para armazenar uma cadeia de caracteres de caracteres de texto. Bem isso é vários KB não utilizados ali. As aplicações fazem muito isso, e é para isso que o overcommit foi projetado.

Então, basicamente, com overcommit em 100, o kernel não permitirá que os aplicativos aloquem mais memória do que você tem (swap + ram). Configurá-lo em menos de 100 significa que você nunca usará toda a sua memória. Se você vai definir essa configuração, você deve defini-la acima de 100 por causa do cenário mencionado anteriormente, o que é bastante comum.

Agora, quanto ao seu problema com o acionamento do killer da OOM, a configuração manual de overcommit provavelmente não corrigirá isso. A configuração padrão (determinação heurística) é bastante inteligente.

Se você deseja ver se essa é realmente a causa do problema, veja /proc/meminfo quando o killer da OOM for executado. Se você vir que Committed_AS está próximo de CommitLimit , mas free ainda está exibindo memória livre disponível, então sim, você pode ajustar manualmente a supercomprometimento do seu cenário. Definir esse valor como muito baixo fará com que o killer da OOM comece a matar aplicativos quando você ainda tiver bastante memória livre. Configurá-lo muito alto pode fazer com que aplicativos aleatórios morram ao tentar usar a memória em que foram alocados, mas na verdade não está disponível (quando toda a memória realmente se esgotar).

    
por 22.02.2012 / 13:45
20

A seção 9.6 "Overcommit and OOM" no documento que @dunxd menciona é particularmente gráfica sobre os perigos de permitir supercomprometimento. No entanto, o 80 também me pareceu interessante, por isso fiz alguns testes.

O que eu descobri é que overcommit_ratio afeta o total de RAM disponível para todos os processos. Os processos raiz não parecem ser tratados de forma diferente dos processos normais do usuário.

A definição da proporção para 100 ou menos deve fornecer a semântica clássica na qual os valores de retorno de malloc/sbrk são confiáveis. A definição de proporções inferiores a 100 pode ser uma maneira de reservar mais RAM para atividades que não são de processo, como armazenamento em cache e assim por diante.

Portanto, no meu computador com 24 GiB de RAM, com a troca desativada, 9 GiB em uso, com top mostrando

Mem:  24683652k total,  9207532k used, 15476120k free,    19668k buffers
Swap:        0k total,        0k used,        0k free,   241804k cached

Aqui estão algumas configurações de overcommit_ratio e quanta RAM meu programa consumidor de RAM pode pegar (tocando em cada página) - em cada caso, o programa saiu limpo uma vez malloc falhou.

 50    ~680 MiB
 60   ~2900 MiB
 70   ~5200 MiB
100  ~12000 MiB

A execução de vários de uma só vez, mesmo com alguns como o usuário raiz, não alterou o valor total consumido juntos. É interessante que não foi possível consumir os últimos 3+ GiB ou mais; o free não caiu muito abaixo do mostrado aqui:

Mem:  24683652k total, 20968212k used,  3715440k free,    20828k buffers

Os experimentos eram confusos - tudo o que usa malloc no momento em que toda RAM está em uso tende a travar, já que muitos programadores são péssimos em verificar falhas malloc em C, algumas bibliotecas populares ignoram-nas completamente, e C ++ e vários outros línguas são ainda piores.

A maioria das implementações iniciais de RAM imaginária que vi foi para lidar com um caso muito específico, onde um único processo grande - digamos 51% + de memória disponível - precisava de fork() para exec() algum programa de suporte, geralmente muito, muito menor. Sistemas operacionais com semântica copy-on-write permitiriam o fork() , mas com a condição de que se o processo bifurcado realmente tentasse modificar muitas páginas de memória (cada uma delas teria que ser instanciada como uma nova página independente da inicial processo enorme) acabaria sendo morto. O processo pai estava apenas em perigo se alocando mais memória, e poderia lidar com o esgotamento, em alguns casos apenas esperando um pouco para que algum outro processo morra, e então continuando. O processo filho normalmente apenas se substituiu a um programa (normalmente menor) via exec() e ficou livre da condição.

O conceito de supercomprometimento do Linux é uma abordagem extrema para permitir que ambos os fork() ocorram, bem como para permitir que processos únicos sejam maciçamente sobrecarregados. As mortes causadas por OOM killer acontecem de forma assíncrona, até mesmo para programas que fazem a alocação de memória de maneira responsável. Eu pessoalmente odeio overcommit em todo o sistema em geral e o assassino em particular - ele promove uma abordagem de gerenciamento de memória que infecta bibliotecas e, através delas, todos os aplicativos que as utilizam.

Eu sugeriria configurar a proporção para 100, e ter uma partição swap também que geralmente só acabaria sendo usada por processos enormes - que geralmente usam apenas uma fração pequena da parte deles mesmos que é colocada em swap. e, assim, proteger a grande maioria dos processos do mau funcionamento do OOM killer. Isso deve manter seu servidor seguro contra a morte aleatória, e se ele foi escrito para lidar com malloc com responsabilidade, até mesmo a salvo de se matar (mas não aposte no último).

Isso significa que estou usando isso em /etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100
    
por 25.05.2013 / 18:28