Se um processo exigir muita memória, o sistema move todos os outros processos para o arquivo de troca. Incluindo, parece, processos necessários, como o servidor X11 ou o terminal.
Portanto, se um processo continua alocando sem limite, tudo fica sem resposta, até que esse processo seja morto pelo assassino de OOM. Meu laptop parece ser especialmente sensível e reage extremamente mal. Passei uma HORA INTEIRA aguardando o término do processo durante o qual nem o cursor do mouse poderia ser movido.
Como isso pode ser evitado?
1) Desative a troca => Geralmente inicio muitos processos que ficam inativos. Os inativos devem ser movidos para a troca.
2) Consiga um SSD => muito caro
3) defina um máximo de memória ulimit =>, mas falhará nos casos em que um programa precise de uma quantidade grande e razoável de memória. o problema não é que ele usa muito, mas suprime os outros processos
4) mantenha programas importantes (X11, bash, kill, top, ...) na memória e nunca troque esses => isso pode ser feito? quão? talvez apenas troque programas grandes?
5)
Respostas:
TL; DR
Temporário / resposta curta
ulimit -v
, verifique e talvez defina um limite rígido ou flexível usando aas
opção inlimits.conf
). Isso costumava funcionar bem o suficiente, mas graças à introdução do WebKitgigacage
, muitos aplicativos gnome agora esperam espaços de endereço ilimitados e não conseguem executar!sysctl vm.overcommit_memory
,sysctl vm.overcommit_ratio
, mas esta abordagem não deu certo para mim.Eu também encontrei:
Solução a longo prazo
espere e espere que alguns patches upstream entrem em kernels de distribuição estáveis. Também esperamos que os fornecedores de distribuição melhor sintonizem os padrões do kernel e alavancem melhor os grupos de sistemas para priorizar a capacidade de resposta da GUI nas edições de desktop.
Alguns patches de interesse:
Portanto, não é apenas um código de espaço do usuário ruim e as configurações / padrões da distro que estão com defeito - o kernel poderia lidar com isso melhor.
Comentários sobre opções já consideradas
É recomendável fornecer pelo menos uma pequena partição de troca ( realmente precisamos de troca em sistemas modernos? ). Desabilitar a troca não apenas impede a troca de páginas não utilizadas, mas também pode afetar a estratégia de supercompressão heurística padrão do kernel para alocar memória (o que significa heurística em Overcommit_memory = 0 significa? ), Pois essa heurística conta com páginas de troca. Sem troca, a supercompromisso ainda pode provavelmente funcionar nos modos heurístico (0) ou sempre (1), mas a combinação da estratégia de não troca e da nunca (2) supercomprovação provavelmente é uma péssima idéia. Portanto, na maioria dos casos, nenhuma troca provavelmente prejudicará o desempenho.
Por exemplo, pense em um processo de execução demorada que inicialmente toque na memória para trabalho único, mas que falhe ao liberar essa memória e continue executando o plano de fundo. O kernel precisará usar a RAM para isso até o processo terminar. Sem nenhuma troca, o kernel não pode paginar por outra coisa que realmente queira usar a RAM ativamente. Pense também em quantos desenvolvedores são preguiçosos e não liberam explicitamente a memória após o uso.
Aplica-se apenas por processo, e provavelmente é uma suposição razoável de que um processo não deva solicitar mais memória que um sistema possui fisicamente! Portanto, é provavelmente útil impedir que um processo louco e solitário desencadeie uma surra enquanto ainda está sendo generosamente definido.
Boa ideia, mas esses programas consumirão memória que não estão sendo usados ativamente. Pode ser aceitável se o programa solicitar apenas uma quantidade modesta de memória.
A versão systemd 232 acabou de adicionar algumas opções que tornam isso possível: Eu acho que alguém poderia usar o 'MemorySwapMax = 0' para impedir que uma unidade (serviço) como o ssh tenha sua memória trocada.
No entanto, ser capaz de priorizar o acesso à memória seria melhor.
Explicação longa
O kernel do linux é mais otimizado para as cargas de trabalho do servidor, portanto a capacidade de resposta da GUI infelizmente foi uma preocupação secundária ... As configurações de gerenciamento de memória do kernel na edição para desktop do Ubuntu 16.04 LTS não pareciam diferir das outras edições do servidor. Ele ainda corresponde aos padrões no RHEL / CentOS 7.2 normalmente usados como servidor.
OOM, ulimit e troca de integridade por capacidade de resposta
A troca de trocas (quando o conjunto de memória de trabalho, ou seja, as páginas que estão sendo lidas e gravadas em um determinado período de tempo excede a RAM física) sempre bloqueia a E / S de armazenamento - nenhuma mágica do kernel pode salvar um sistema disso sem interromper um processo ou dois...
Espero que os ajustes do OOM do Linux que surjam nos kernels mais recentes reconheçam que este conjunto de trabalho excede a situação da memória física e mata um processo. Quando isso não acontece, o problema surra. O problema é que, com uma grande partição de swap, pode parecer que o sistema ainda possui espaço livre enquanto o kernel se compromete e ainda atende solicitações de memória, mas o conjunto de trabalho pode se espalhar para o swap, tratando efetivamente o armazenamento como se é RAM.
Nos servidores, ele aceita a penalidade de desempenho do thrashing para uma troca determinada, lenta e sem perda de dados. Nos desktops, a troca é diferente e os usuários preferem um pouco de perda de dados (sacrifício de processos) para manter as coisas responsivas.
Essa foi uma boa analogia cômica sobre OOM: oom_pardon, aka não mate meu xlock
Aliás,
OOMScoreAdjust
é outra opção do sistema para ajudar a pesar e evitar processos de destruição de OOM considerados mais importantes.write-back com buffer
Eu acho que " Fazer a gravação em segundo plano não ser uma merda " ajudará a evitar alguns problemas nos quais um processo que monopoliza a RAM causa outra troca (gravação em disco) e a gravação em massa no disco interrompe qualquer outra coisa que deseje IO. Não é a causa do problema em si, mas contribui para a degradação geral da capacidade de resposta.
limitação ulimits
Um problema com ulimits é que o limite de contabilidade se aplica ao espaço de endereço da memória virtual (o que implica combinar o espaço físico e o swap). Conforme
man limits.conf
:Portanto, definir um ulimit para aplicar apenas ao uso físico da RAM não parece mais utilizável. Conseqüentemente
parece ser o único respeitável sintonizador.
Infelizmente, conforme detalhado no exemplo do WebKit / Gnome, alguns aplicativos não podem ser executados se a alocação de espaço de endereço virtual for limitada.
cgroups deve ajudar no futuro?
Atualmente, parece complicado, mas é possível ativar alguns sinalizadores de cgroup do kernel
cgroup_enable=memory swapaccount=1
(por exemplo, na configuração do grub) e tente usar o controlador de memória cgroup para limitar o uso da memória.O cgroups possui recursos de limite de memória mais avançados que as opções 'ulimit'. As notas do CGroup v2 sugerem tentativas de melhorar o funcionamento dos ulimits.
As opções do CGroup podem ser definidas através das opções de controle de recursos do systemd . Por exemplo:
Outras opções úteis podem ser
Estes têm alguns inconvenientes:
No CGroup v2 , eles sugerem que
memory.high
deve ser uma boa opção para controlar e gerenciar o uso de memória por um grupo de processos. No entanto, esta citação sugere que o monitoramento de situações de pressão de memória precisava de mais trabalho (a partir de 2015).Dado que as ferramentas de espaço do usuário systemd e cgroup são complexas, não encontrei uma maneira simples de definir algo apropriado e aproveitar isso ainda mais. A documentação do cgroup e systemd para o Ubuntu não é ótima. O trabalho futuro deve ser para distros com edições de desktop para alavancar cgroups e systemd, para que, sob alta pressão de memória, os componentes ssh e X-Server / gerenciador de janelas tenham acesso de maior prioridade à CPU, RAM física e E / S de armazenamento, para evitar competir com os processos troca ocupada. Os recursos de prioridade de E / S da CPU e do kernel já existem há algum tempo. Parece ser o acesso prioritário à RAM física que está faltando.
No entanto, nem mesmo as prioridades de CPU e E / S estão definidas adequadamente !? Quando verifiquei os limites do systemd cgroup, os compartilhamentos da CPU, etc. aplicados, até onde eu sabia, o Ubuntu não havia funcionado em nenhuma priorização predefinida. Por exemplo, eu corri:
Comparei isso com a mesma saída para ssh, samba, gdm e nginx. Coisas importantes, como a GUI e o console de administração remota, têm que lutar igualmente com todos os outros processos quando ocorre a debulha.
Limites de memória de exemplo que tenho em um sistema de 16 GB de RAM
Eu queria ativar a hibernação, então precisava de uma grande partição de troca. Daí a tentativa de mitigar com ulimits, etc.
ulimit
Eu coloquei
* hard as 16777216
de/etc/security/limits.d/mem.conf
tal forma que nenhum processo único poderia solicitar mais memória do que é fisicamente possível. Não evitarei debater todos juntos, mas sem isso, apenas um único processo com uso de memória ganancioso, ou um vazamento de memória, pode causar debulha. Por exemplo, eu vignome-contacts
consumir mais de 8 GB de memória ao fazer coisas comuns, como atualizar a lista de endereços global de um servidor de troca ...Como visto
ulimit -S -v
, muitas distros têm esse limite rígido e flexível definido como "ilimitado", dado que, em teoria, um processo pode acabar solicitando muita memória, mas apenas ativamente usando um subconjunto, e rodando feliz pensando que foi concedido, digamos, 24 GB de RAM enquanto o sistema possui apenas 16 GB. O limite rígido acima fará com que os processos que podem ter sido capazes de executar corretamente sejam interrompidos quando o kernel negar suas solicitações de memória especulativa gananciosas.No entanto, ele também captura coisas insanas, como contatos do gnome, e em vez de perder a capacidade de resposta da minha área de trabalho, recebo o erro "memória insuficiente":
Complicações configurando ulimit para espaço de endereço (memória virtual)
Infelizmente, alguns desenvolvedores gostam de fingir que a memória virtual é um recurso infinito e definir um limite na memória virtual pode quebrar alguns aplicativos. Por exemplo, o WebKit (do qual alguns aplicativos gnome dependem) adicionou um
gigacage
recurso de segurança que tenta alocar quantidades insanas de memória virtual eFATAL: Could not allocate gigacage memory
erros com uma dica atrevidaMake sure you have not set a virtual memory limit
. A solução alternativa,GIGACAGE_ENABLED=no
renuncia aos benefícios de segurança, mas, da mesma forma, não é permitido limitar a alocação de memória virtual também renuncia a um recurso de segurança (por exemplo, controle de recursos que pode impedir a negação de serviço). Ironicamente, entre os desenvolvedores de gigacage e gnome, eles parecem esquecer que limitar a alocação de memória é um controle de segurança. E, infelizmente, notei que os aplicativos gnome que dependem de gigacage não se preocupam em solicitar explicitamente um limite mais alto; portanto, mesmo um limite suave interrompe as coisas nesse caso.Para ser justo, se o kernel fez um trabalho melhor em negar a alocação de memória com base no uso da memória residente em vez da memória virtual, fingir que a memória virtual é ilimitada seria menos perigoso.
comprometer
Se você preferir que os aplicativos tenham acesso negado à memória e queira interromper o comprometimento excessivo, use os comandos abaixo para testar como o sistema se comporta quando está sob alta pressão de memória.
No meu caso, a taxa de confirmação padrão era:
Mas isso só entra em vigor ao alterar a política para desativar o excesso de confirmação e aplicar a taxa
A proporção implicada em que apenas 24 GB de memória pode ser alocada no geral (16 GB de RAM * 0,5 + 16 GB de SWAP). Portanto, eu provavelmente nunca veria o OOM aparecer, e seria menos provável que os processos acessassem constantemente a memória em troca. Mas provavelmente também sacrificarei a eficiência geral do sistema.
Isso fará com que muitos aplicativos travem, pois é comum que os desenvolvedores não manejem normalmente o sistema operacional que recusa uma solicitação de alocação de memória. Ele elimina o risco ocasional de um bloqueio prolongado devido a surtos (solte todo o seu trabalho após uma reinicialização forçada) a um risco mais frequente de vários aplicativos travarem. Nos meus testes, não ajudou muito porque a própria área de trabalho travou quando o sistema estava sob pressão de memória e não pôde alocar memória. No entanto, pelo menos consoles e SSH ainda funcionavam.
Como a VM supercomprime a memória funciona tem mais informações.
Eu escolhi voltar ao padrão para isso,
sudo sysctl -w vm.overcommit_memory=0
considerando toda a pilha gráfica da área de trabalho e os aplicativos nela travados.fonte
but the kernel won't be able to use an overcommit strategy for allocating memory and this will likely hurt performance. Even a smaller swap partition allows this.
Existe alguma prova disso? Acredito overcommits do kernel muito bem sem troca configurado