Wie kann dieses Speicherproblem ordnungsgemäß gelöst werden?


10

Ich habe einen Standard-Linux-Laptop (Debian-Test) mit einer Swap-Partition.

Ich mache viele Experimente damit. Einige von ihnen sind wirklich speicherhungrig und die Art und Weise, wie sich Linux standardmäßig verhält, ist ein Problem für mich ... Lassen Sie uns ein dummes Beispiel geben:

  1. Setzen Sie sich vor den Laptop
  2. Öffnen Sie ein Terminal
  3. Geben Sie pythondann eina = [0]*100000000

Jetzt stehen die Chancen gut, dass Sie nicht genug RAM haben, um diese große Liste zu bearbeiten. Linux füllt den RAM, dann den Swap und ein paar Minuten später wird der OOM-Killer ausgelöst und (fast) zufällige Dienste beendet, und hoffentlich, wenn Sie zum richtigen Zeitpunkt Strg + C drücken python, und wenn das Terminal Hatte noch Fokus, wird der Computer wieder reagieren.

Ich möchte einige Speicherbeschränkungen durchsetzen, um dieses unerwünschte Austauschen zu vermeiden und einem Prozess das Recht zu verweigern, mehr Speicher zuzuweisen als ich (im RAM). Wenn der Speicherbedarf unter einem bestimmten Grenzwert liegt oder von root angefordert wird, beenden Sie einfach den speicherhungrigsten Prozess eines Benutzers mit Ausnahme von root.

ulimit -Sv [mem] Ich höre hinten!

Ho Ho! "Verwenden Sie cgroupsvia cgexec!" sagt jemand in der ersten Reihe!

Ja, Sie haben Recht: Dies sind in der Tat sehr gute Lösungen. Aber:

  • Sie gelten nicht systemweit
  • Die Grenzen werden pro Prozess festgelegt
  • Die Grenzwerte sind statisch, unabhängig von der tatsächlichen Menge an freiem RAM (AFAIK).
  • Hier und da sagen sie, dass dies keine wirklich gute Lösung ist, um harte Grenzen durchzusetzen.

Was ich möchte ist, dass der Kernel sagt: "Du gehörst zum Benutzer foo (nicht root), du verwendest viel Speicher und wir werden keinen Speicher mehr haben. Tut mir leid, Alter ... stirb jetzt!"

Oder: "Was zum Teufel machst du? Du brauchst x MB und es sind nur y MB verfügbar. Ja, SWAP ist leer, aber du hast nicht vor, SWAP für deine Drecksarbeit zu verwenden, oder? Nein, ich sagte nein! Keine Erinnerung für dich! Wenn du darauf bestehst, wirst du sterben! "


2
In diesem Artikel ist bereits ein Algorithmus beschrieben, der dem OOM-Killer hilft, den richtigen Prozess auszuwählen. Das Ändern /proc/sys/vm/overcommit_memorywirkt sich auf das Kernelverhalten bei geringem Arbeitsspeicher aus.
Jofel

1
Ja, aber die overcommit_memoryspezielle Datei verwendet RAM + SWAP als verwendbaren Speicher. Ich werde immer noch tauschen :)

1
Sie müssen auch erklären, dass dies kein Duplikat davon ist: unix.stackexchange.com/questions/34334/…, was Ihren WRT-Gruppen und einzelnen Benutzern widerspricht. PS. Wenn Sie nicht tauschen möchten, deaktivieren Sie den Austausch .
Goldlöckchen

1
Ich will tauschen! Ich möchte den Ruhezustand, ich möchte, dass nicht verwendete Bytes gespeichert werden! Ich möchte aber nicht, dass verwendete Bytes dort gespeichert werden. Über den Link, ulimitssind eine schlechte Idee, wie fast überall gezeigt, da es sich um eine pro-Prozess-Einschränkung handelt ... Ich weiß, Sie wissen :) Über cgroups, das ist definitiv besser, aber es fehlt etwas allgemeineres: Ich spreche über meinen Laptop, aber ich auch Besitzen Sie einen "Berechnungs" -Server, den wir drei gemeinsam nutzen können. Wenn ich solche Limits pro Benutzer erzwinge, werde ich durch das Worst-Case-Szenario eingeschränkt, nicht wahr?

1
cgroups gelten für jeden Prozess, für den Sie sich entscheiden. Ordnen Sie alle Prozesse eines Benutzers einer separaten Gruppe zu, und es sollte das tun, was Sie wollen.
Peterph

Antworten:


4

Jemand hat in Ihrem Hören vorgeschlagen cgroups. Versuchen Sie, diese Richtung zu suchen, da sie Ihnen Folgendes bieten kann:

  • angewendet auf eine Gruppe von Aufgaben, die Sie auswählen (also nicht systemweit, aber auch nicht pro Prozess)
  • Die Grenzen werden für die Gruppe festgelegt
  • Die Grenzen sind statisch
  • Sie können eine harte Speicherbeschränkung und / oder Speicher + Austausch erzwingen

So etwas könnte Sie Ihren Zielen näher bringen :

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

Dies zeigt an, dass die Aufgaben unter dieser Gruppe nur maximal 50 MB Speicher und 50 MB Speicher + Swap verwenden können. Wenn der Speicher also voll ist, wird er nicht ausgetauscht, aber wenn der Speicher nicht voll ist und einige Daten zugeordnet werden könnten tauschen, das könnte erlaubt sein.

Hier ist ein Auszug aus der Speicherdokumentation der Gruppe :

Durch die Verwendung von memsw limit können Sie System-OOM vermeiden, die durch Swap-Mangel verursacht werden können.


Immer noch nicht genau das, was ich erwartet hatte. Aber der Unterschied zwischen dem, was ich erwarte, und der Realität ist oft ziemlich groß :) In diesem Fall wollte ich sicher sein, dass ich nichts wie die overcommit_memoryKernelvariable verpasst habe . Danke euch allen.

0

Ich stoße häufig auf das gleiche Problem. Mein allgemeiner Workflow beinhaltet umfangreiche Berechnungen in MATLAB. Gelegentlich werde ich versehentlich versuchen, eine neue Variable zuzuweisen, die die Menge des verfügbaren Speichers überschreitet. Das System hängt und ich muss den Computer normalerweise hart neu starten, um wieder arbeiten zu können. : P.

In meinem Fall, und es klingt auch in Ihrem Fall, ging es mir nicht so sehr darum, die von MATLAB verwendete Speichermenge auf eine statische Menge zu beschränken. Ich war daran interessiert, keine eingefrorene Maschine zu haben, und ich war bereit, meinen MATLAB-Prozess zu opfern um die Reaktionsfähigkeit des Systems zu erhalten.

Inspiriert von einer Antwort auf diesen Beitrag schrieb ich das folgende Skript (ich nannte es 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

Dieses Skript überprüft jede Sekunde den prozentualen Anteil an freiem Speicher. Wenn das System ausgeht, wird Ihre "Sündenbock" -PID (als Argument an das Skript übergeben) getötet.

Ohne die Priorität (Freundlichkeit) des Skripts anzupassen, dauerte es ungefähr 10 bis 20 Sekunden, bis der Sündenbock getötet wurde, aber es funktionierte immer noch. Das Ausführen des Skripts mit einer negativen Priorität führte zu einem sofortigen Abbruch nach einer Verletzung (11916 in diesem Beispiel ist die PID, die ich beenden möchte, wenn mir der Speicher ausgeht):

sudo nice -n -5 bash watch_memory.sh 11916
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.