Come risolvere questo problema di memoria con garbo?


10

Ho un laptop standard Linux (test Debian), con una partizione di swap.

Faccio molti esperimenti con esso. Alcuni di loro sono davvero affamati di memoria e il modo in cui Linux si comporta di default è un problema per me ... Facciamo un esempio stupido:

  1. Siediti di fronte al laptop
  2. Apri un terminale
  3. Digita python, quindia = [0]*100000000

Ora è molto probabile che non avrai abbastanza RAM per gestire quella grande lista. Linux riempirà la RAM, quindi lo swap e, un paio di minuti dopo, il killer OOM verrà attivato e ucciderà (quasi) servizi casuali e, si spera, se premi Ctrl + C nel momento giusto pythone se il terminale ancora focalizzato, il computer tornerà reattivo.

Vorrei imporre alcuni limiti di memoria per evitare lo scambio indesiderato e rifiutare a un processo il diritto di allocare più memoria di quella che ho (nella RAM). Se la richiesta di memoria è al di sotto di un certo limite o viene richiesta da root, è sufficiente interrompere il processo più affamato di memoria di qualsiasi utente tranne root.

ulimit -Sv [mem] Sento nella parte posteriore!

Ho Ho! "Usa cgroupsvia cgexec!" qualcuno dice in prima fila!

Sì, hai ragione: queste sono davvero ottime soluzioni. Ma:

  • Non si applicano a tutto il sistema
  • I limiti sono impostati per processo
  • I limiti sono statici, ignorando la quantità reale di RAM libera (AFAIK)
  • Qua e , dicono che questi non sono davvero una buona soluzione per imporre limiti rigidi.

Quello che mi piacerebbe è che il kernel dica: "Tu appartieni all'utente foo (non root), usi molta memoria e finiremo la memoria. Scusa amico ... muori ora!"

Oppure: "Che diavolo stai facendo? Hai bisogno di x MB e sono disponibili solo y MB. Sì, SWAP è vuoto, ma non intendi utilizzare SWAP per fare il tuo sporco lavoro, vero? No, io ha detto di no! Nessun ricordo per te! Se insisti, morirai! "


2
C'è già un algoritmo descritto in questo articolo che aiuta il killer OOM a scegliere il processo corretto. La modifica /proc/sys/vm/overcommit_memoryinfluisce sul comportamento del kernel in memoria insufficiente.
jofel,

1
Sì, ma il overcommit_memoryfile speciale utilizza RAM + SWAP come memoria utilizzabile.

1
Devi anche spiegare come questo non sia un duplicato di questo: unix.stackexchange.com/questions/34334/… che contraddice te cgroups WRT e singoli utenti. PS. Se non si desidera scambiare, disabilitare lo scambio .
Riccioli d'oro

1
Voglio scambiare! Voglio l'ibernazione, voglio che i byte non utilizzati vengano archiviati! Ma non voglio che i byte usati vengano archiviati lì. Riguardo al link, ulimitssono una cattiva idea, come mostrato quasi ovunque poiché è una limitazione per processo ... I fork lo sai :) A proposito cgroups, questo è sicuramente meglio ma manca qualcosa di più generale: sto parlando del mio laptop ma anche possedere un server di "calcolo" che siamo in tre a condividere. Se impongo tali limiti per utente, sarò limitato dallo scenario peggiore, no?

1
i cgroup si applicano a qualsiasi processo tu decida, metti tutti i processi di un utente in un gruppo separato e dovrebbe fare quello che vuoi.
peterph,

Risposte:


4

Qualcuno ha suggerito nel tuo ascolto cgroups. Bene, prova a cercare quella direzione in quanto può fornirti:

  • applicato a un gruppo di attività scelto (quindi non a livello di sistema ma né per processo)
  • i limiti sono stabiliti per il gruppo
  • i limiti sono statici
  • possono imporre limiti rigidi alla memoria e / o alla memoria + scambio

Qualcosa del genere potrebbe avvicinarti ai tuoi obiettivi :

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

Ciò indica che le attività in questo cgroup possono utilizzare al massimo 50 M di memoria e 50 M di memoria + scambio, quindi quando la memoria è piena, non si scambia, ma se la memoria non è piena e alcuni dati potrebbero essere mappati in scambiare, questo potrebbe essere permesso.

Ecco un estratto dalla documentazione di memoria del cgroup :

Utilizzando il limite memsw, è possibile evitare la OOM di sistema che può essere causata dalla carenza di swap.


Non è esattamente quello che mi aspettavo. Ma la differenza tra ciò che mi aspetto e la realtà è spesso piuttosto grande :) In questo caso, volevo essere sicuro di non aver perso nulla come la overcommit_memoryvariabile del kernel. Grazie a tutti.

0

Mi imbatto spesso nello stesso problema. Il mio flusso di lavoro generale comporta un calcolo pesante in MATLAB. Occasionalmente tenterò inavvertitamente di allocare una nuova variabile che supera la quantità di memoria disponibile. Il sistema si blocca e in genere devo riavviare la macchina per tornare al lavoro. : P

Nel mio caso, e sembra anche nel tuo, non ero molto preoccupato di limitare la quantità di memoria che MATLAB usa a una quantità statica - ero interessato a non avere una macchina congelata ed ero disposto a sacrificare il mio processo MATLAB al fine di preservare la reattività del sistema.

Ispirato da una risposta a questo post , ho scritto il seguente script (l'ho chiamato 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

Questo script controlla ogni secondo la quantità percentuale di memoria libera. Quando il sistema si esaurisce, il pid "capro espiatorio" (passato come argomento allo script) viene ucciso.

Senza modificare la priorità (gentilezza) della sceneggiatura, ci sono voluti circa 10-20 secondi prima che il capro espiatorio venisse ucciso, ma funzionava ancora. L'esecuzione dello script con una priorità negativa ha provocato un'uccisione istantanea dopo la violazione (11916 in questo esempio è il pid che voglio uccidere se esaurisco la memoria):

sudo nice -n -5 bash watch_memory.sh 11916
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.