Wie fülle ich 90% des freien Speichers?

181

Ich möchte einige ressourcenschonende Tests durchführen und dafür muss der freie Speicher zu 90% voll sein.

Wie kann ich das auf einem *nixSystem machen?

Eduard Florinescu
quelle
3
Muss es wirklich auf jedem * nix-System funktionieren?
ein Lebenslauf vom
31
Könnten Sie stattdessen eine virtuelle Maschine (mit Docker, Vagrant oder ähnlichem) erstellen, die nur über einen begrenzten Arbeitsspeicher verfügt?
Abendigo
4
@abendigo Für eine Qualitätssicherung sind viele der hier vorgestellten Lösungen hilfreich: Für ein Allzweck-Betriebssystem ohne eine bestimmte Plattform könnten die VM- oder Kernel-Boot-Parameter hilfreich sein, für ein eingebettetes System hingegen, bei dem Sie die Speicherspezifikation des Zielsystems kennen gehen Sie für das Füllen des freien Speichers.
Eduard Florinescu
2
Für den Fall, dass jemand ein bisschen schockiert ist über die Wertung hier: meta.unix.stackexchange.com/questions/1513/… ?
Goldlöckchen

Antworten:

157

stress-ng ist ein Workload-Generator, der die Belastung von POSIX-Systemen durch CPU / Mem / IO / HDD simuliert. Dieser Aufruf sollte unter Linux <3.14 funktionieren:

stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

Unter Linux> = 3.14 können Sie MemAvailablestattdessen den verfügbaren Arbeitsspeicher für neue Prozesse schätzen, ohne den Arbeitsspeicher auszutauschen:

stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

Passen Sie den /proc/meminfoAufruf mit free(1)/ vm_stat(1)/ etc an. wenn Sie es tragbar brauchen.

tkrennwa
quelle
3
stress --vm-bytes $ (awk '/ MemFree / {printf "% d \ n", $ 2 * 0.097;}' </ proc / meminfo) k --vm-keep -m 10
Robert
1
Der größte Teil von MemFree wird vom Betriebssystem verwaltet, daher habe ich stattdessen MemAvailable verwendet. Dies gab mir 92% Auslastung auf Cent OS 7.stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
kujiy
Gut zu wissen, MemAvailable wurde hinzugefügt, um zu schätzen, wie viel Speicher zum Starten neuer Anwendungen verfügbar ist, ohne diese auszutauschen. … Und git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/…
tkrennwa
1
Nur als zusätzliche Anmerkung, vorausgesetzt, beide --vm 1 and --vm-keepsind sehr wichtig. Wenn --vm-bytesSie einfach nichts tun, werden Sie möglicherweise in die Irre geführt und denken, Sie können so viel Speicher zuweisen, wie Sie benötigen / möchten. Ich habe ein bisschen davon mitbekommen, bis ich versucht habe, mich durch Zuweisen von 256 GB Speicher auf meine Gesundheit zu überprüfen. Dies ist kein Fehler in der Antwort, sondern liefert die korrekten Flags, nur eine zusätzliche Warnung.
ffledgling
Deshalb gibt es -m 1. Laut der Manpage zu Stress -m Nist die --vm NNmalloc()/free()
Abkürzung
92

Sie können ein C-Programm in malloc()den erforderlichen Speicher schreiben und dann verwenden mlock(), um zu verhindern, dass der Speicher ausgelagert wird.

Lassen Sie das Programm einfach auf die Tastatureingabe warten und entsperren Sie den Speicher. Geben Sie den Speicher frei und beenden Sie das Programm.

Chris
quelle
25
Vor langer Zeit musste ich ähnliche Anwendungsfälle testen. Ich habe festgestellt, dass der Speicher erst zugewiesen wird, wenn Sie etwas in diesen Speicher schreiben (dh bis ein Seitenfehler auftritt). Ich bin mir nicht sicher, ob mlock () sich darum kümmert.
Poorna
2
Ich stimme mit @siri überein; Dies hängt jedoch davon ab, welche UNIX-Variante Sie verwenden.
Anthony
2
Etwas Inspiration für den Code. Darüber hinaus glaube ich, dass Sie den Speicher nicht entsperren / freigeben müssen . Das Betriebssystem erledigt das für Sie, wenn Ihr Prozess beendet ist.
Sebastian
9
Wahrscheinlich müssen Sie tatsächlich in den Speicher schreiben. Der Kernel könnte ein Overcommit ausführen, wenn Sie ihn nur mallocieren. Wenn dies konfiguriert ist, lässt Linux beispielsweise malloc erfolgreich zurückkehren, ohne dass tatsächlich Speicher frei ist, und reserviert den Speicher nur dann, wenn in ihn geschrieben wird. Siehe win.tue.nl/~aeb/linux/lk/lk-9.html
Bjarke Freund-Hansen
7
@ Sebastian: callocwird auf das gleiche Problem IIRC laufen. Der gesamte Speicher zeigt nur auf dieselbe schreibgeschützte Seite mit Nullen. Es wird erst zugewiesen, wenn Sie versuchen, darauf zu schreiben (was nicht funktioniert, da es schreibgeschützt ist). Der einzige Weg, um wirklich sicher zu sein, dass ich es weiß, ist, einen memsetTeil des gesamten Puffers zu machen. Weitere Informationen finden
Leo
45

Ich würde vorschlagen, eine VM mit begrenztem Speicher auszuführen und die Software darin zu testen, was ein effizienterer Test wäre als der Versuch, den Speicher auf dem Hostcomputer zu füllen.

Diese Methode hat auch den Vorteil, dass Sie nur die zu testende VM hängen und nicht die Maschine, auf der möglicherweise andere nützliche Prozesse ausgeführt werden, wenn die Situation mit wenig Arbeitsspeicher an anderer Stelle OOM-Fehler verursacht und das gesamte Betriebssystem blockiert.

Auch wenn Ihre Tests nicht CPU- oder E / A-intensiv sind, können Sie Instanzen der Tests gleichzeitig auf einer Familie von VMs mit einer Vielzahl von geringen Speichergrößen ausführen.

David Spillett
quelle
31

Aus diesem HN-Kommentar: https://news.ycombinator.com/item?id=6695581

Füllen Sie einfach / dev / shm über dd oder ähnliches.

swapoff -a
dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k
damio
quelle
8
Nicht alle * Nixe haben / dev / shm. Noch eine tragbare Idee?
Tadeusz A. Kadłubowski
Wenn pvinstalliert ist, hilft es, die Anzahl zu sehen:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Otheus
1
Wenn Sie Geschwindigkeit wollen, ist diese Methode die richtige Wahl! Weil es in Sekundenschnelle die gewünschte Menge an RAM zuweist. Relay nicht auf / dev / urandom, es wird 100% der CPU verbraucht und einige Minuten dauern, wenn Ihr RAM groß ist. NOCH hat / dev / shm in modernen Ubuntu / Debian-Distributionen eine relative Größe, die standardmäßig 50% des physischen Arbeitsspeichers beträgt. Hoffentlich können Sie / dev / shm erneut einhängen oder einen neuen Einhängepunkt erstellen. Stellen Sie einfach sicher, dass es die tatsächliche Größe hat, die Sie zuweisen möchten.
develCuy
30
  1. starte Linux;
  2. booten Sie mit dem mem=nn[KMG]Kernel-Boot-Parameter

(Details finden Sie in linux / Documentation / kernel-parameters.txt).

Anon
quelle
24

Wenn Sie grundlegenden GNU - Tools haben ( sh, grep, yesund head) Sie können dies tun:

yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily

Dies funktioniert, weil grep die gesamte Datenzeile in den Arbeitsspeicher lädt (ich habe dies auf eine ziemlich unglückliche Weise erfahren, als ich ein Disk-Image gegriffen habe). Die Zeile, die durch das yesErsetzen von Zeilenumbrüchen generiert wird, ist unendlich lang, aber headauf $BYTESBytes begrenzt, sodass grep $ BYTES in den Speicher lädt. Grep selbst verwendet für mich etwa 100-200 KB. Möglicherweise müssen Sie dies subtrahieren, um einen genaueren Betrag zu erhalten.

Wenn Sie auch eine Zeitbeschränkung hinzufügen möchten, können Sie dies ganz einfach in ausführen bash(funktioniert nicht in sh):

cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n

Das <(command)Ding scheint wenig bekannt zu sein, ist aber oft sehr nützlich. Weitere Informationen dazu finden Sie hier: http://tldp.org/LDP/abs/html/process-sub.html

Dann gilt für die Verwendung von cat: catfür Eingaben abgeschlossen warten , bis Verlassen und durch eines der Rohre offen zu halten, wird es grep am Leben zu halten.

Wenn Sie den pvRAM-Verbrauch langsam erhöhen möchten und müssen :

yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n

Zum Beispiel:

yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n

Verbraucht bis zu einem Gigabyte bei einer Rate von 1 MB pro Sekunde. Als zusätzlichen Bonus pvwerden Ihnen die aktuelle Nutzungsrate und die bisherige Gesamtnutzung angezeigt. Dies kann natürlich auch mit vorherigen Varianten durchgeführt werden:

yes | tr \\n x | head -c $BYTES | pv | grep n

Durch einfaches Einfügen des | pv |Teils wird der aktuelle Status angezeigt (Durchsatz und Gesamtmenge, denke ich, standardmäßig - ansonsten wird die Man-Seite (ual) angezeigt).


Warum noch eine Antwort? In der akzeptierten Antwort wird empfohlen, ein Paket zu installieren (ich wette, es gibt eine Version für jeden Chipsatz, für die kein Paketmanager erforderlich ist). In der Antwort mit der höchsten Bewertung wird empfohlen, ein C-Programm zu kompilieren (für die Kompilierung für Ihre Zielplattform war weder ein Compiler noch eine Toolchain installiert). Die zweithäufigste Antwort empfiehlt, die Anwendung in einer virtuellen Maschine auszuführen (ja, lassen Sie mich einfach die interne SD-Karte dieses Telefons über USB oder so etwas austauschen und ein Virtualbox-Image erstellen). der dritte schlägt vor, etwas in der Startsequenz zu ändern, das den RAM nicht wie gewünscht füllt; Der vierte funktioniert nur, sofern der / dev / shm-Mountpoint (1) existiert und (2) groß ist (Remounting benötigt root). der fünfte kombiniert viele der oben genannten ohne Beispielcode; Die sechste ist eine großartige Antwort, aber ich habe diese Antwort nicht gesehen, bevor ich meinen eigenen Ansatz gefunden habe. Also dachte ich, ich würde mein eigenes hinzufügen, auch weil es kürzer ist, sich zu erinnern oder umzuschreiben, wenn man nicht sieht, dass die Memblob-Linie tatsächlich der springende Punkt ist. das siebte beantwortet die Frage nicht (verwendet stattdessen ulimit, um einen Prozess einzuschränken); Der achte versucht, Sie dazu zu bringen, Python zu installieren. Die neunte hält uns alle für sehr unkreativ, und schließlich hat die zehnte ihr eigenes C ++ - Programm geschrieben, das das gleiche Problem verursacht wie die Antwort, für die die meisten Stimmen abgegeben haben.

Luc
quelle
schöne lösung. Der einzige Nachteil ist, dass der Exit-Code des Konstrukts 1 ist, da grep keine Übereinstimmung findet. Keine der Lösungen von stackoverflow.com/questions/6550484/… scheint das Problem zu beheben.
Holger Brandl
@ HolgerBrandl Guter Punkt, ich würde nicht wissen, wie man das behebt. Dies ist das erste Mal, dass ich davon hörte set -e, also habe ich gerade etwas gelernt :)
Luc
$ SECONDS scheint keine gute Wahl zu sein, da es sich um eine eingebaute Variable handelt, die die Zeit seit dem Start der Shell widerspiegelt. siehe tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Holger Brandl
@HolgerBrandl Guter Fang, das wusste ich nicht. Irgendwie cool, ein Terminal zu finden, das derzeit für> 3 Millionen Sekunden geöffnet ist: D. Ich habe den Beitrag aktualisiert.
Luc
Coole Technik! time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n(benutze 10 GiB Speicher) dauert 1 Minute 46 Sekunden. Das Ausführen des Programms eatmemory von julman99 unter github.com/julman99/eatmemory dauert 6 Sekunden. ... Nun, plus der Download- und Kompilierungszeit, aber ohne Probleme kompiliert ... und sehr schnell ... auf meinem RHEL6.4-Rechner. Trotzdem mag ich diese Lösung. Warum das Rad neu erfinden?
Mike S
18

Ich behalte eine Funktion, um etwas Ähnliches in meinen Punktedateien zu tun. https://github.com/sagotsky/.dotfiles/blob/master/.functions#L248

function malloc() {
  if [[ $# -eq 0 || $1 -eq '-h' || $1 -lt 0 ]] ; then
    echo -e "usage: malloc N\n\nAllocate N mb, wait, then release it."
  else 
    N=$(free -m | grep Mem: | awk '{print int($2/10)}')
    if [[ $N -gt $1 ]] ;then 
      N=$1
    fi
    sh -c "MEMBLOB=\$(dd if=/dev/urandom bs=1MB count=$N) ; sleep 1"
  fi
}
Valadil
quelle
1
Dies ist meiner Meinung nach die schönste Lösung, da sie im Wesentlichen nur dd benötigt, um zu funktionieren. Alle anderen Dinge können in jeder Shell umgangen werden. Man beachte, dass es tatsächlich das Doppelte des Speichers beansprucht, als die Daten, die dd erzeugt, zumindest vorübergehend. Getestet unter Debian 9, Dash 0.5.8-2.4. Wenn Sie den MEMBLOB-Teil mit bash ausführen, wird er sehr langsam und verbraucht das Vierfache der von dd erzeugten Menge.
P.Péter
16

Wie viel kostet eine einfache Python-Lösung?

#!/usr/bin/env python

import sys
import time

if len(sys.argv) != 2:
    print "usage: fillmem <number-of-megabytes>"
    sys.exit()

count = int(sys.argv[1])

megabyte = (0,) * (1024 * 1024 / 8)

data = megabyte * count

while True:
    time.sleep(1)
schneller Kodierer
quelle
7
Das wird wahrscheinlich schnell ausgetauscht und hat nur sehr geringe Auswirkungen auf den Speicherdruck (es sei denn, Sie füllen auch den gesamten Swap auf, was normalerweise eine Weile dauern wird)
Joachim Sauer,
1
Warum sollte ein Unix-Swap durchgeführt werden, solange RAM verfügbar ist? Dies ist eine plausible Möglichkeit, den Festplatten-Cache bei Bedarf zu löschen.
Alexander Shcheblikin
@AlexanderShcheblikin Bei dieser Frage geht es nicht darum, den Festplatten-Cache zu löschen (dies ist nützlich für Leistungstests, aber nicht für Tests mit geringen Ressourcen).
Gilles
1
Diese Lösung hat in meinen Tests ein oder zwei Gig gekostet, obwohl ich nicht versucht habe, mein Gedächtnis zu strapazieren. Aber, @JoachimSauer, man könnte vm.min_free_kbytes setzen sysctl vm.swappiness=0und außerdem auf eine kleine Zahl setzen, vielleicht 1024. Ich habe es nicht ausprobiert, aber die Dokumentation sagt, dass Sie auf diese Weise die Schnelligkeit des Austauschs steuern ... Sie sollten es sein in der Lage, es in der Tat ziemlich langsam zu machen, bis ein OOM-Zustand auf Ihrem Computer verursacht wird. Siehe kernel.org/doc/Documentation/sysctl/vm.txt und kernel.org/doc/gorman/html/understand/understand005.html
Mike S,
Einfach ein Liner für 1 GB: python -c "x = (1 * 1024 * 1024 * 1024/8) * (0,); raw_input ()"
adrianlzt
10

Wie wäre es mit Ramfs, wenn es existiert? Hängen Sie es ein und kopieren Sie über eine große Datei? Wenn es keine /dev/shmund keine RAMFS gibt - ich denke, ein kleines C-Programm, das einen großen Malloc basierend auf einem Eingabewert ausführt? Möglicherweise muss es auf einem 32-Bit-System mit viel Speicher mehrere Male gleichzeitig ausgeführt werden.

nemo
quelle
8

Wenn Sie einen bestimmten Prozess mit begrenztem Speicher testen möchten, ist es möglicherweise besser ulimit, die Menge des zuweisbaren Speichers zu beschränken.

sj26
quelle
2
Tatsächlich funktioniert dies nicht unter Linux (keine Ahnung über andere * Nixe). man setrlimit:RLIMIT_RSS Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM). This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.
Patrick
4

Ich denke, dies ist ein Fall, in dem die falsche Frage gestellt wird und die Vernunft von Leuten übertönt wird, die um die kreativste Antwort konkurrieren. Wenn Sie nur OOM-Bedingungen simulieren müssen, müssen Sie den Speicher nicht füllen. Verwenden Sie einfach einen benutzerdefinierten Allokator und lassen Sie ihn nach einer bestimmten Anzahl von Allokationen fehlschlagen. Dieser Ansatz scheint für SQLite gut genug zu funktionieren .

Craig Barnes
quelle
3

Ich habe dieses kleine C ++ - Programm dafür geschrieben: https://github.com/rmetzger/dynamic-ballooner

Der Vorteil dieser Implementierung besteht darin, dass regelmäßig überprüft wird, ob Speicher freigegeben oder neu zugewiesen werden muss.

Robert Metzger
quelle