Como resolver esse problema de memória normalmente?

10

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

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

  1. Sente-se em frente ao laptop
  2. Abra um terminal
  3. Digite python e, em seguida, a = [0]*100000000

Agora, há grandes chances de você não ter RAM suficiente para lidar com essa lista grande. O Linux preencherá a RAM, depois a troca e, alguns minutos depois, o killer da OOM será acionado e matará (quase) serviços aleatórios e, se tudo correr bem, se você pressionar Ctrl + C, python e se o terminal ainda tiver foco, o computador voltará a responder.

Eu 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 eu (na RAM). Se a demanda de memória estiver abaixo de um determinado limite ou for solicitada pelo root, basta matar o processo que mais requer memória de qualquer usuário, exceto o root.

ulimit -Sv [mem] Eu ouço pelas costas!

Ho Ho! "Use cgroups via cgexec !" Alguém diz na primeira fila!

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

  • Eles não se aplicam em todo o sistema
  • Os limites são definidos por processo
  • Os limites são estáticos, desconsiderando a quantidade real de uma RAM livre (AFAIK)
  • Aqui e aqui , 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 diga: "Você pertence ao usuário foo (não é root), você usa muita memória e nós ficaremos sem memória. ... morra agora! "

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

    
por Community 12.02.2013 / 13:48

2 respostas

4

Alguém sugeriu na sua conta cgroups . Bem, tente buscar essa direção, pois ela pode fornecer:

  • aplicado a um grupo de tarefas que você escolhe (portanto, não no sistema inteiro, mas nem por processo)
  • os limites estão definidos para o grupo
  • os limites são estáticos
  • eles podem reforçar o limite de memória e / ou memória + swap

Algo assim pode aproximá-lo dos seus objetivos :

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

Isto diz que as tarefas sob este cgroup podem usar no máximo 50M de memória e 50M de memória + swap, então quando a memória estiver cheia, ele não irá trocar, mas se a memória não estiver cheia e alguns dados puderem ser mapeado no swap, isso poderia ser permitido.

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

By using memsw limit, you can avoid system OOM which can be caused by swap shortage.

    
por 12.02.2013 / 15:42
0

Eu me deparo com o mesmo problema com freqüência. Meu fluxo de trabalho geral envolve cálculos pesados no MATLAB. Ocasionalmente, tentarei inadvertidamente alocar uma nova variável que exceda a quantidade de memória disponível. O sistema trava, e eu normalmente tenho que reinicializar a máquina para voltar ao trabalho. : P

No meu caso, e soa como no seu também, eu não estava tão 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 eu estava disposto a sacrificar meu processo do MATLAB para preservar a capacidade de resposta do sistema.

Inspirado por uma resposta a este post , eu escreveu o seguinte script (chamei-o 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 cada segundo quanto à quantidade percentual de memória livre. Quando o sistema se esgota, o seu "bode expiatório" pid (passado como argumento para o script) é morto.

Sem ajustar a prioridade (gentileza) do script, demorou cerca de 10 a 20 segundos para o bode expiatório ser morto, mas ainda funcionava. Executar o script com uma prioridade negativa resultou em um kill after after instantâneo (11916 neste exemplo é o pid que eu quero matar se ficar sem memória):

sudo nice -n -5 bash watch_memory.sh 11916

Espero que isso ajude!

    
por 03.06.2014 / 20:38