Como resolver esse problema de memória normalmente?

10

Eu tenho um laptop Linux (teste Debian) padrão, com uma partição swap.

Eu faço muitas experiências com isso. Alguns deles têm muita memória e a maneira como o Linux se comporta por padrão é um problema para mim ... Vamos dar um exemplo estúpido:

  1. Sente-se na frente do laptop
  2. Abra um terminal
  3. Digite python, entãoa = [0]*100000000

Agora são grandes as chances de você não ter RAM suficiente para lidar com essa grande lista. O Linux preencherá a RAM, depois a troca e, alguns minutos depois, o OOM killer será acionado e matará (quase) serviços aleatórios e, esperançosamente, se você pressionar Ctrl + C na hora certa python, e se o terminal ainda tinha o foco, o computador se tornaria responsivo novamente.

Gostaria de impor alguns limites de memória para evitar essa troca indesejada e recusar a um processo o direito de alocar mais memória do que tenho (na RAM). Se a demanda de memória estiver abaixo de um determinado limite ou solicitada pelo root, basta matar o processo que mais consome memória de qualquer usuário, exceto o root.

ulimit -Sv [mem] Eu ouço lá atrás!

Ho Ho! "Use cgroupsvia cgexec!" alguém diz na primeira linha!

Sim, você está certo: estas são realmente muito boas soluções. Mas:

  • Eles não se aplicam a todo o sistema
  • Os limites são definidos por processo
  • Os limites são estáticos, desconsiderando a quantidade real de RAM livre (AFAIK)
  • Aqui e ali , eles dizem que essas não são realmente uma boa solução para impor limites rígidos.

O que eu gostaria é que o kernel dissesse: "Você pertence ao usuário foo (não root), você usa muita memória e nós ficaremos sem memória. Desculpe cara ... morra agora!"

Ou: "O que diabos você está fazendo? Você precisa de x MB e há apenas y MB disponíveis. Sim, o SWAP está vazio, mas você não pretende usá-lo para fazer seu trabalho sujo, não é? disse que não! Não há memória para você! Se você insistir, vai morrer! "

Comunidade
fonte
2
Já existe um algoritmo descrito neste artigo que ajuda o assassino do OOM a escolher o processo correto. A alteração /proc/sys/vm/overcommit_memoryafeta o comportamento do kernel com pouca memória.
Jofel
1
Sim, mas o overcommit_memoryarquivo especial usa RAM + SWAP como memória utilizável. Eu ainda vou trocar :) #
1
Você também precisa explicar como isso não é uma duplicata: unix.stackexchange.com/questions/34334/… que contradiz os cgroups do WRT e usuários individuais. PS. Se você não deseja trocar, desative a troca .
goldilocks
1
Eu quero trocar! Quero hibernação, quero que bytes não utilizados sejam armazenados! Mas não quero que os bytes usados sejam armazenados lá. Sobre o link, ulimitssão uma péssima idéia, como mostrado em quase todos os lugares, pois é uma limitação por processo ... Eu garfo você sabe :) Sobre cgroups, isso é definitivamente melhor, mas falta algo mais geral: estou falando do meu laptop, mas também possuir um servidor de "cálculo" que somos três para compartilhar. Se eu aplicar esses limites por usuário, ficarei limitado pelo pior cenário, não é?
1
Os cgroups se aplicam a qualquer processo que você decidir - coloque todos os processos de um usuário em um grupo separado e deve fazer o que você deseja.
Peterph

Respostas:

4

Alguém sugeriu em seu ouvido cgroups. Bem, tente buscar essa direção, pois ela pode fornecer:

  • aplicado a um grupo de tarefas que você escolher (portanto, não em todo o sistema, mas nem por processo)
  • os limites são definidos para o grupo
  • os limites são estáticos
  • eles podem impor limites rígidos à memória e / ou memória + troca

Algo assim poderia aproximá-lo de seus objetivos :

group limited {
  memory {
    memory.limit_in_bytes = 50M;
    memory.memsw.limit_in_bytes = 50M;
  }
}

Isso indica que as tarefas desse cgroup podem usar no máximo 50M de memória apenas e 50M de memória + swap, portanto, quando a memória estiver cheia, ela não será trocada, mas se a memória não estiver cheia e alguns dados puderem ser mapeados. swap, isso pode ser permitido.

Aqui está um trecho da documentação da memória do cgroup :

Ao usar o limite memsw, você pode evitar o OOM do sistema, que pode ser causado pela falta de troca.

Huygens
fonte
Ainda não exatamente o que eu estava esperando. Mas a diferença entre o que eu espero e a realidade geralmente é bastante grande :) Nesse caso, eu queria ter certeza de que não perdi nada como a overcommit_memoryvariável do kernel. Obrigado a todos.
0

Eu sempre encontro o mesmo problema. Meu fluxo de trabalho geral envolve computação pesada no MATLAB. Ocasionalmente, tentarei inadvertidamente alocar uma nova variável que exceda a quantidade de memória disponível. O sistema trava e normalmente tenho que reiniciar a máquina para voltar ao trabalho. : P

No meu caso, e parece que o seu também, eu não estava muito preocupado em limitar a quantidade de memória que o MATLAB usa para uma quantidade estática - eu estava interessado em não ter uma máquina congelada e estava disposto a sacrificar meu processo do MATLAB para preservar a capacidade de resposta do sistema.

Inspirado por uma resposta a este post , escrevi o seguinte script (chamei de watch_memory.sh):

#!/bin/bash

MONITOR=$(free | grep 'buffers/cache:')
MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')

MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))

while :; do
    if [ "$MEM_PERC" -gt "95" ]
    then
        kill $1
        echo "$1 killed for using too much memory."
        exit
    fi
    sleep 1

    MONITOR=$(free | grep 'buffers/cache:')
    MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
    MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')
    MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))
done

Este script verifica a cada segundo a quantidade percentual de memória livre. Quando o sistema acaba, o pid "bode expiatório" (passado como argumento para o script) é morto.

Sem ajustar a prioridade (gentileza) do script, demorou de 10 a 20 segundos para o bode expiatório ser morto, mas ainda funcionou. A execução do script com uma prioridade negativa resultou em uma morte instantânea após a violação (11916 neste exemplo é o pid que eu quero matar se ficar sem memória):

sudo nice -n -5 bash watch_memory.sh 11916
Gordon Bean
fonte