Ich bin ein wenig verwirrt über einige der Ergebnisse, die ich sehe vonpsUndfrei.
Auf meinem Server ist dies das Ergebnis vonfree -m
[root@server ~]# free -m
total used free shared buffers cached
Mem: 2048 2033 14 0 73 1398
-/+ buffers/cache: 561 1486
Swap: 2047 11 2036
Nach meinem Verständnis verwaltet Linux den Speicher so, dass es die Festplattennutzung im RAM speichert, damit jeder nachfolgende Zugriff schneller erfolgt. Ich glaube, dies wird durch die Spalten „zwischengespeichert“ angezeigt. Darüber hinaus werden verschiedene Puffer im RAM gespeichert, die in der Spalte „Puffer“ angezeigt werden.
Wenn ich das also richtig verstehe, soll die „tatsächliche“ Nutzung der „verwendete“ Wert von „-/+ Puffer/Cache“ sein, also in diesem Fall 561.
Wenn ich also davon ausgehe, dass das alles richtig ist, sind es die Ergebnisse von, die mich verwirren ps aux
.
Nach meinem Verständnis der ps
Ergebnisse stellt die 6. Spalte (RSS) die Größe in Kilobyte dar, die der Prozess als Speicher nutzt.
Wenn ich also diesen Befehl ausführe:
[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52
Sollte das Ergebnis nicht die Spalte „verwendet“ von „-/+ Puffer/Cache“ sein free -m
?
Wie kann ich also den Speicherverbrauch eines Prozesses unter Linux richtig bestimmen? Offenbar ist meine Logik fehlerhaft.
Antwort1
Schamloses Kopieren/Einfügen meiner Antwort vonServerfehlererst vor Kurzem :-)
Das virtuelle Speichersystem von Linux ist nicht ganz so einfach. Sie können nicht einfach alle RSS-Felder addieren und den used
von gemeldeten Wert erhalten free
. Dafür gibt es viele Gründe, aber ich werde einige der wichtigsten nennen.
Wenn sich ein Prozess verzweigt, werden sowohl der übergeordnete als auch der untergeordnete Prozess mit demselben RSS angezeigt. Linux verwendet jedoch Copy-on-Write, sodass beide Prozesse tatsächlich denselben Speicher verwenden. Nur wenn einer der Prozesse den Speicher ändert, wird er tatsächlich dupliziert.
Dies führt dazu, dass diefree
Zahl kleiner ist als dietop
RSS-Summe.Der RSS-Wert umfasst keinen gemeinsam genutzten Speicher. Da der gemeinsam genutzte Speicher keinem einzelnen Prozess gehört,
top
wird er nicht in RSS einbezogen.
Dies führt dazu, dass diefree
Zahl größer ist als dietop
RSS-Summe.
Es gibt viele andere Gründe, warum die Zahlen nicht stimmen. Diese Antwort soll nur verdeutlichen, dass die Speicherverwaltung sehr komplex ist und Sie nicht einfach einzelne Werte addieren/subtrahieren können, um die gesamte Speichernutzung zu ermitteln.
Antwort2
Wenn Sie nach Zahlen suchen, die sich addieren, schauen Sie sich an untersmem:
smem ist ein Tool, das zahlreiche Berichte zur Speichernutzung auf Linux-Systemen erstellen kann. Im Gegensatz zu vorhandenen Tools kann smem die proportionale Setgröße (PSS) melden, die eine aussagekräftigere Darstellung der Speichermenge ist, die von Bibliotheken und Anwendungen in einem virtuellen Speichersystem verwendet wird.
Da große Teile des physischen Speichers normalerweise von mehreren Anwendungen gemeinsam genutzt werden, wird die Speichernutzung mit der als Resident Set Size (RSS) bezeichneten Standardmessung der Speichernutzung erheblich überschätzt. PSS misst stattdessen den „fairen Anteil“ jeder Anwendung an jedem gemeinsam genutzten Bereich, um ein realistisches Maß zu erhalten.
Zum Beispiel hier:
# smem -t
PID User Command Swap USS PSS RSS
...
10593 root /usr/lib/chromium-browser/c 0 22868 26439 49364
11500 root /usr/lib/chromium-browser/c 0 22612 26486 49732
10474 browser /usr/lib/chromium-browser/c 0 39232 43806 61560
7777 user /usr/lib/thunderbird/thunde 0 89652 91118 102756
-------------------------------------------------------------------------------
118 4 40364 594228 653873 1153092
Das PSS
ist die interessante Spalte hier, weil sie den gemeinsam genutzten Speicher berücksichtigt.
Im Gegensatz dazu RSS
ist es sinnvoll, ihn zu addieren. Wir erhalten hier insgesamt 654 MB für Userland-Prozesse.
Über den Rest informiert die systemweite Ausgabe:
# smem -tw
Area Used Cache Noncache
firmware/hardware 0 0 0
kernel image 0 0 0
kernel dynamic memory 345784 297092 48692
userspace memory 654056 181076 472980
free memory 15828 15828 0
----------------------------------------------------------
1015668 493996 521672
Also insgesamt 1 GB RAM = 654 MB Userland-Prozesse + 346 MB Kernelspeicher + 16 MB frei
(plus/minus ein paar MB)
Insgesamt wird etwa die Hälfte des Speichers für den Cache verwendet (494 MB).
Bonus-Frage: Was ist hier der Userland-Cache im Vergleich zum Kernel-Cache?
Versuchen Sie übrigens für etwas Visuelles:
# smem --pie=name
Antwort3
Ein wirklich gutes Tool ist pmap
, das die aktuelle Speichernutzung für einen bestimmten Prozess auflistet:
pmap -d PID
Weitere Informationen hierzu finden Sie auf der Manpage man pmap
sowie unter20 Linux-Systemüberwachungstools, die jeder Systemadministrator kennen sollte, in der großartige Tools aufgelistet sind, die ich immer verwende, um Informationen zu meiner Linux-Box zu erhalten.
Antwort4
Wie andere bereits richtig angemerkt haben, ist es aufgrund gemeinsam genutzter Regionen, mmap-Dateien und dergleichen schwierig, den tatsächlichen Speicherverbrauch eines Prozesses zu ermitteln.
Wenn Sie ein Experimentator sind, können SieValgrind und Massiv. Dies kann für den Gelegenheitsnutzer etwas schwerfällig werden, aber Sie erhalten eine Vorstellung vom Speicherverhalten einer Anwendung im Laufe der Zeit. Wenn eine Anwendung malloc() genau das ist, was sie braucht, erhalten Sie hierdurch eine gute Darstellung der tatsächlichen dynamischen Speichernutzung eines Prozesses. Dieses Experiment kann jedoch „vergiftet“ werden.
Um die Sache noch komplizierter zu machen, ermöglicht Linux IhnenÜberlastungIhr Speicher. Wenn Sie Speicher mit malloc() verwenden, geben Sie Ihre Absicht an, Speicher zu verbrauchen. Die Zuweisung erfolgt jedoch erst dann wirklich, wenn Sie ein Byte auf eine neue Seite Ihres zugewiesenen „RAM“ schreiben. Sie können sich dies selbst beweisen, indem Sie ein kleines C-Programm wie das folgende schreiben und ausführen:
// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
void *p;
sleep(5)
p = malloc(16ULL*1024*1024*1024);
printf("p = %p\n", p);
sleep(30);
return 0;
}
# Shell:
cc test.c -o test && ./test &
top -p $!
Führen Sie dies auf einem Computer mit weniger als 16 GB RAM aus und voilà! Sie haben gerade 16 GB Speicher gewonnen! (nein, nicht wirklich).
Beachten top
Sie, dass bei „VIRT“ 16.004G angezeigt wird, %MEM jedoch 0,0 ist.
Führen Sie dies erneut mit Valgrind aus:
# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30
Und Massif sagt „Summe aller Allocs() = 16 GB“. Das ist also nicht sehr interessant.
ABER, wenn Sie es auf einemvernünftigVerfahren:
# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30
--------------------------------------------------------------------------------
Command: cc test.c -o test
Massif arguments: (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------
KB
77.33^ :
| #:
| :@::@:#:
| :::::@@::@:#:
| @:: :::@@::@:#:
| ::::@:: :::@@::@:#:
| ::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
| :@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
0 +----------------------------------------------------------------------->Mi
0 1.140
Und hier sehen wir (sehr empirisch und mit sehr hoher Sicherheit), dass der Compiler 77 KB Heap zugewiesen hat.
Warum sollte man sich so sehr darum bemühen, nur die Heap-Nutzung zu erreichen? Weil alle gemeinsam genutzten Objekte und Textabschnitte, die ein Prozess verwendet (in diesem Beispiel der Compiler), nicht besonders interessant sind. Sie sind ein ständiger Overhead für einen Prozess. Tatsächlich sind nachfolgende Aufrufe des Prozesses fast „kostenlos“.
Vergleichen Sie außerdem Folgendes und kontrastieren Sie es:
MMAP() eine 1 GB große Datei. Ihre VMSize wird 1+GB sein. Ihre Resident Set Size wird jedoch nur die Teile der Datei sein, die Sie ausgelagert haben (indem Sie einen Zeiger auf diesen Bereich dereferenziert haben). Und wenn Sie die ganze Datei „lesen“, hat der Kernel möglicherweise bereits die Anfänge ausgelagert, wenn Sie am Ende angekommen sind (das ist einfach, weil der Kernel genau weiß, wie/wo diese Seiten ersetzt werden müssen, wenn sie erneut dereferenziert werden). In beiden Fällen sind weder VMSize noch RSS ein guter Indikator für Ihre Speichernutzung. Sie haben tatsächlich nichts mit malloc() bearbeitet.
Im Gegensatz dazu verwenden Malloc() und touch VIEL Speicher – bis Ihr Speicher auf die Festplatte ausgelagert wird. Ihr zugewiesener Speicher übersteigt jetzt also Ihren RSS. Hier könnte Ihre VMSize Ihnen etwas sagen (Ihr Prozess besitzt mehr Speicher als sich tatsächlich in Ihrem RAM befindet). Aber es ist immer noch schwierig, zwischen VMs mit gemeinsam genutzten Seiten und VMs mit ausgelagerten Daten zu unterscheiden.
Hier wird valgrind/massif interessant. Es zeigt Ihnen, was Sieabsichtlichzugewiesen (unabhängig vom Status Ihrer Seiten).