Speicherverbrauch unter Linux richtig ermitteln

Speicherverbrauch unter Linux richtig ermitteln

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 psErgebnisse 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 usedvon 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 die freeZahl kleiner ist als die topRSS-Summe.

  • Der RSS-Wert umfasst keinen gemeinsam genutzten Speicher. Da der gemeinsam genutzte Speicher keinem einzelnen Prozess gehört, topwird er nicht in RSS einbezogen.
    Dies führt dazu, dass die freeZahl größer ist als die topRSS-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 PSSist die interessante Spalte hier, weil sie den gemeinsam genutzten Speicher berücksichtigt.
Im Gegensatz dazu RSSist 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

Bildbeschreibung hier eingeben

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 pmapsowie 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 topSie, 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).

verwandte Informationen