Como pode haver um cenário OOM no Linux (heurística por trás do killer da OOM)?

1

Estou ciente do conceito de memória virtual. E com a paginação por demanda (dependendo de vm.overcommit_memory), você pode alocar mais memória do que a RAM disponível. A menos que você "toque" em uma página, nada realmente acontece. Senão eu acho que há uma falha de página e memória física é usada para o quadro de página. Mas isso, de alguma forma, implica que, se o sistema estiver apertado na memória, ele acabará paginando as últimas coisas usadas recentemente e funcionará normalmente.

Como pode haver a necessidade de matar um processo? Isso acontece porque muita memória é mlock () - ed. A OOM é invocada depois de haver muita lixeira? Ou para perguntar de forma diferente: o que exatamente são as heurísticas por trás do acionamento do assassino da OOM?

Eu li que você poderia fazer "echo 1 > memory.oom_control" ou "echo -17 > / proc / PID / oom_adj" para desativá-lo. Quais são as implicações disso? A máquina provavelmente ficará totalmente sem resposta por um tempo. Mas se, de alguma forma, o processo ofensivo detectar que ele não progride, ele também poderá parar temporariamente de consumir memória (tão rápido) e, eventualmente, tudo deve começar a funcionar novamente ou estou enganado?

No meu cenário, há apenas um processo (que tem um enorme cache na memória). Esses dados não são persistentes, é claro, mas eu ainda prefiro não reiniciar o processo (e recarregar esses dados).

    
por fiction 05.05.2016 / 00:35

1 resposta

2

Você parece estar confuso sobre como a memória virtual e o excesso de comprometimento estão relacionados.

A memória física consiste nos chips de RAM do seu computador. É fisicamente impossível usar mais mais memória ao mesmo tempo que a memória física. No entanto, desde o final da década de 1970, houve memória virtual, em que o sistema transferirá alguns dados da memória física para o disco, armazenando memória que não está sendo usada para que a memória física possa ser usada para outras coisas. Quando isso acontece, os programas não podem usar imediatamente os dados que foram trocados; quando eles tentarem fazer isso de qualquer maneira, o processador gerará uma falha de página , fazendo com que o sistema operacional carregue os dados necessários de volta para a memória física.

Usando a memória virtual, a quantidade total de dados em trânsito que podem estar em uso é estendida para o tamanho da memória física mais o espaço de troca. Enquanto isso permite que o sistema execute mais programas ao mesmo tempo, a quantidade de memória realmente em uso nunca pode exceder a memória total disponível virtual (ou seja, RAM + espaço de troca )

Em princípio, o kernel deve manter o controle da quantidade de memória que os programas solicitaram, e deve rejeitar pedidos de mais memória, uma vez que sua contabilidade informa que toda a memória foi alocada , mesmo que nem todos tenham sido usados . A maioria dos outros kernels faz isso, e então eles não têm um killer OOM (porque eles não precisam de um).

No entanto, a chamada do sistema para um programa para alocar memória do kernel não aloca memória pelo byte; aloca-o por blocos maiores. Em contraste, a implementação real usada pela maioria dos programas para obter memória (a função de biblioteca malloc() C) faz permitir que os programas aloquem memória pelo byte. O que isto significa é que a maioria dos programas, quando eles pedem alguma memória, acabam com malloc() alocando mais do que eles realmente precisam. Além disso, uma boa implementação de malloc() utilizará algumas heurísticas para manter alocações menores e maiores separadas, para que a fragmentação da memória não seja ruim, mas isso exige que ela solicite mais memória do kernel, exacerbando o problema. Como resultado desses e de outros efeitos, sem comprometer demais, haverá grandes quantidades de memória alocadas, mas nunca serão usadas.

A idéia de supercomprometimento é que você pode alocar com segurança alguns mais memória do que a quantidade total de memória virtual que seu sistema tem disponível sem que ele seja executado de volta. Em essência, o kernel afirma que permite uma alocação, mesmo sabendo que não pode cumprir com essa promessa, na suposição de que não precisará viver até o limite total dessas promessas. No entanto, a quantia exata que pode ser supercomprometida - alocada - sem que coisas nunca dêem errado não pode ser prevista; Assim, quando o kernel detectar que os programas estão tentando usar toda a memória que foram alocados, o kernel terá que renegar suas promessas. É aqui que entra o assassino da OOM.

Se isso é uma boa ideia, é para debate. Quando o sistema ficar sem memória, algo vai dar errado. Se esse for o caso de algum aplicativo tentando alocar mais memória, mas o kernel já tiver reservado tudo, possivelmente esse aplicativo em particular irá falhar. Se isso acontecer de você ser o seu servidor X, você está sem sorte. Pelo menos se houver um assassino de OOM, ele pode decidir qual processo matar, em vez de coisas ficarem ruins depois de uma má alocação; e o killer da OOM tem alguma lógica para evitar a morte de processos importantes, como o seu servidor X ...

No entanto, se você preferir, existem alguns botões sysctl que você pode usar para desativar a supercomprometimento, você acha que é uma má idéia.

    
por 05.05.2016 / 02:29

Tags