A combinação de três fatos causa seu problema: tamanho pequeno de página , grande VIRT , pagetables . Seus registros mostram claramente que quase toda a RAM era usada por páginas de páginas, não por memória de processo (por exemplo, não por páginas RESID - essas eram pressionadas para trocar).
A chatice das pagetables x86_64 / x86 é que quando você tem vários processos mapeando exatamente a mesma região da memória compartilhada, eles mantêm as tabelas de páginas separadas . Portanto, se um processo mapear 1 TB (incluído no VIRT), o kernel criará 1 GB de tabela de páginas (não mostradas em top
, pois elas não são contadas como pertencentes a um processo). Mas, se cem processos mapeiam a mesma área de 1 TB, eles ocupam 100 GB de sua memória RAM para armazenar, de forma redunoravel, os mesmos metadados!
A quantidade de VIRT de um único processo pode ser simplesmente causada pela abertura e mmaping de um arquivo (nomeado ou "anônimo"), embora possa haver muitas explicações alternativas.
Eu acho que o assassino não leva em conta o tamanho dos pagetables ao matar um processo. No seu caso, aparentemente o mongodb foi o principal candidato para o kill kill em termos de uso do RES. Apesar do ganho de memória ser minúsculo, o sistema não tinha escolha, então ele matava o que poderia matar.
A maneira mais óbvia de evitar o seu problema seria usar páginas enormes , se apenas o mongodb as suportasse (não estou sugerindo usar páginas enormes e transparentes, em vez disso, considerar páginas enormes não transparentes de baunilha ). A pesquisa superficial diz que infelizmente o mongodb não suporta páginas enormes nem transparentes.
Outra maneira é limitar o número de processos gerados ou de alguma forma diminuir seu tamanho de VIRT.