Feststellen der Speichernutzung unter Linux


63

Ich bin ein bisschen verwirrt über einige der Ergebnisse, die ich von ps und free sehe .

Auf meinem Server ist dies das Ergebnis von free -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 der Speicherverwaltung unter Linux wird die Festplattennutzung im RAM gespeichert, sodass jeder nachfolgende Zugriff schneller erfolgt. Ich glaube, das wird durch die "zwischengespeicherten" Spalten angezeigt. Zusätzlich werden verschiedene Puffer im RAM gespeichert, die in der Spalte "Puffer" angegeben sind.

Wenn ich das richtig verstehe, sollte die "tatsächliche" Verwendung der "verwendete" Wert von "- / + Buffer / Cache" sein, oder 561 in diesem Fall.

Unter der Annahme, dass all dies richtig ist, ist der Teil, der mich wirft, das Ergebnis von ps aux.

Mein Verständnis der psErgebnisse ist, dass die 6. Spalte (RSS) die Größe in Kilobyte darstellt, die der Prozess für den Speicher verwendet.

Wenn ich diesen Befehl ausführe:

[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52

Sollte das Ergebnis nicht die "verwendete" Spalte von "- / + Buffer / Cache" sein free -m?

Wie kann ich die Speichernutzung eines Prozesses unter Linux richtig bestimmen? Anscheinend ist meine Logik fehlerhaft.


Diese Frage ist sehr beliebt und ich denke, ich sollte eine Antwort des htopAutors auf eine ähnliche Frage teilen, die ich neulich
tgogos

Antworten:


57

Diese genaue gleiche Frage wurde am gefragt serverfault nur den anderen Tag :-)

Das Linux Virtual Memory System ist nicht ganz so einfach. Sie können nicht einfach alle RSS-Felder addieren und den Wert usedvon erhalten free. Es gibt viele Gründe dafür, aber ich werde ein paar der größten treffen.

  • Wenn sich ein Prozess teilt, werden sowohl das übergeordnete als auch das untergeordnete Element mit demselben RSS angezeigt. Allerdings setzt Linux copy-on-writeso ein, dass beide Prozesse tatsächlich den gleichen Speicher belegen. Nur wenn einer der Prozesse den Speicher ändert, wird er tatsächlich dupliziert. Dies führt also dazu, dass die freeZahl kleiner als die topRSS-Summe ist.

  • Der RSS-Wert enthält keinen gemeinsamen Speicher. Da Shared Memory keinem Prozess gehört, wird topes nicht in RSS aufgenommen. Dies führt also dazu, dass die freeAnzahl größer als die topRSS-Summe ist.


1
Dies ist die beste Antwort, die ich bisher auf einer Stack-Exchange-Site erhalten habe. Also genau das was ich wissen wollte. Es ist besonders genau auf meine Situation zugeschnitten, weil ich es mit einem Programm zu tun habe, das ich geschrieben habe, aber der größte Teil des Footprints befindet sich in Bibliotheken, die sie verwenden.
GoldenNewby

Das Problem bei dieser Antwort ist, dass die Berechnung der Summe von RSS und SHR oft viel weniger Speicherplatz ergibt als verbraucht wird. Zum Beispiel auf einem VPS, den ich habe, beläuft sich der verwendete Speicher auf 380 MB, während die Summe aller RSS- und SHR-Daten 90 MB beträgt.
user239558

2
@ user239558 Wie ich in der Antwort erwähnt habe, gibt es viele Gründe, warum sich die Zahlen nicht addieren. Ich habe nur 2 von ihnen aufgelistet. Es gibt viele andere Zahlen; Cache, Platte, große Seiten usw.
Patrick

2
Wahrscheinlich Jahre später, nachdem Sie darauf geantwortet haben, habe ich (mindestens) noch eine Verwirrung. Sie sagten, dass der RSS-Wert keinen gemeinsam genutzten Speicher enthält, aber diese Antwort besagte, dass "es Speicher aus gemeinsam genutzten Bibliotheken enthält, solange sich die Seiten aus diesen Bibliotheken tatsächlich im Speicher befinden". Jetzt weiß ich nicht, an
wen

1
@Naitree "shared libraries"! = "Shared Memory". Shared Memory ist so etwas wie shmgetoder mmap. Die Benennung um Gedächtnismaterial ist sehr schwierig. Die Verwendung des falschen Wortes an der falschen Stelle kann die Bedeutung eines Satzes völlig durcheinander bringen.
Patrick

30

Wenn Sie nach Speicherplatznummern suchen, die sich addieren, schauen Sie sich smem an :

smem ist ein Tool, das zahlreiche Berichte zur Speichernutzung auf Linux-Systemen liefern kann. Im Gegensatz zu vorhandenen Tools kann smem die Proportional Set Size (PSS) melden, eine aussagekräftigere Darstellung der von Bibliotheken und Anwendungen in einem virtuellen Speichersystem verwendeten Speicherkapazität.

Da große Teile des physischen Speichers in der Regel von mehreren Anwendungen gemeinsam genutzt werden, wird die Speichernutzung durch das als RSS (Resident Set Size) bezeichnete Standardmaß für die 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 auch die interessante Spalte hier, weil sie den gemeinsamen Speicher berücksichtigt.
Anders als RSSes sinnvoll ist, es zu addieren. Insgesamt erhalten wir hier 654 MB für Userland-Prozesse.

Die systemweite Ausgabe informiert über den Rest:

# 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 1 GB RAM gesamt = 654 MB Userland-Prozesse + 346 MB Kernel-Mem + 16 MB frei
(geben oder nehmen Sie ein paar MB)

Insgesamt wird ungefähr die Hälfte des Speichers für den Cache verwendet (494 MB).

Bonusfrage : Was ist Userland Cache vs Kernel Cache hier?


Übrigens für etwas visuelles versuchen:

# smem  --pie=name

Bildbeschreibung hier eingeben


14

Ein wirklich gutes Tool, pmapdas die aktuelle Speichernutzung für einen bestimmten Prozess auflistet:

pmap -d PID

Weitere Informationen dazu finden Sie in der Manpage man pmapund unter 20 Linux-Systemüberwachungstools , die jeder SysAdmin kennen sollte . Mit diesen tollen Tools erhalte ich immer Informationen zu meiner Linux-Box.


Das ist ein ziemlich cooles Tool, aber es löst mein Problem nicht wirklich. Ich versuche herauszufinden, wie die "tatsächliche" Speichernutzung auf dem Server effektiv ermittelt werden kann.
GoldenNewby

3
@GoldenNewby Die "tatsächliche" Speichernutzung eines Prozesses gibt es nicht. Die tatsächliche Speichernutzung des Systems gibt freeAuskunft.
Gilles 'SO- hör auf böse zu sein'

pmap -x PIDEnthält auch eine RSS-Spalte, die oft sehr nützlich ist, um eine Vorstellung davon zu bekommen, woher die RSS-Summe eines Prozesses stammt (wie z. B. über beobachtet top).
Maxschlepzig

10

Run top, drücke hum Hilfe und ffüge dann Felder hinzu. Sie können die folgenden Felder hinzufügen:

  • RSS Der von der Anwendung verwendete physische Speicher
  • CODE Gesamtspeicher, den der ausführbare Code des Prozesses belegt
  • DATA - Gesamtspeicher (KB) für die Daten und den Stapel eines Prozesses

Zwischen diesen 3 sollten Sie ziemlich genaue Ergebnisse haben. Sie können auch detailliertere Ersetzungen für Top I empfehlen htopoder verwenden atop.

Bearbeiten: Fast vergessen, wenn Sie wirklich detaillierte Informationen wünschen. Suchen Sie die PID und suchen Sie die folgende Datei.

PID=123

cat /proc/123/status

Bearbeiten 2: Wenn Sie es finden können oder das Buch haben:

Optimieren der Linux-Leistung: Eine praktische Anleitung zu Linux-Leistungstools

-hat einen Abschnitt Kapitel 5: Leistungstools: Prozessspezifischer Speicher -es hat viel mehr Informationen als Sie jemals wollen würden.


Well top hat standardmäßig die RSS-Größe des Prozesses. Top liefert die gleichen Ergebnisse wie "ps aux" in meinem Beispiel. Meine Frage ist, wie kommt es, dass der kombinierte RSS aller Prozesse viel höher ist als die "aktive" Speichernutzung auf dem gesamten Server?
GoldenNewby

5

psgibt an, wie viel Speicher für jeden Prozess benötigt wird. Ein Teil dieses Speichers sind MMAP-Dateien, die im Cache gespeichert werden. Ein Teil dieses Speichers (insbesondere Code) wird mit anderen Prozessen gemeinsam genutzt. Wenn Sie also die RSS-Werte addieren, wird dieser mehrfach gezählt.

Es gibt keine richtige Antwort auf die Frage, wie viel Speicher dieser Prozess belegt, da er nicht nur vom Prozess abhängt, sondern auch von der Umgebung. Es gibt viele verschiedene Werte, die Sie möglicherweise als "Speicherauslastung" des Prozesses bezeichnen. Sie stimmen nicht überein oder summieren sich, weil sie verschiedene Dinge zählen.


4

Wie andere richtig ausgeführt haben, ist es schwierig, einen Überblick über den von einem Prozess tatsächlich verwendeten Speicher zu bekommen, was mit gemeinsam genutzten Bereichen und mit MMAP-Dateien und so weiter.

Wenn Sie ein Experimentator sind, können Sie Valgrind und Massif ausführen . Dies kann für den Gelegenheitsbenutzer etwas schwierig werden, aber Sie erhalten eine Vorstellung vom Speicherverhalten einer Anwendung im Laufe der Zeit. Wenn eine Anwendung malloc () genau das ist, was sie benötigt, erhalten Sie eine gute Darstellung der tatsächlichen dynamischen Speichernutzung eines Prozesses. Aber dieses Experiment kann "vergiftet" werden.

Um die Sache zu verkomplizieren, können Sie unter Linux Ihren Speicher überbelegen . Wenn Sie Speicher malloc (), erklären Sie Ihre Absicht, Speicher zu verbrauchen. Die Zuweisung erfolgt jedoch erst dann, wenn Sie ein Byte in eine neue Seite Ihres zugewiesenen "RAM" schreiben. Sie können sich das 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 Sie haben gerade 16 GB Arbeitsspeicher erzielt! (Nein nicht wirklich).

Beachten topSie, dass "VIRT" als 16.004G angezeigt wird,% MEM jedoch 0.0 ist

Führen Sie dies mit valgrind erneut aus:

# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30

Und das Massiv sagt "Summe aller Zuordnungen () = 16 GB". Das ist also nicht sehr interessant.

ABER, wenn Sie es auf einem vernünftigen Prozess ausführen :

# 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 hohem Vertrauen), dass der Compiler 77 KB Heap zugeteilt hat.

Warum versuchen Sie so hart, nur Heap-Nutzung zu bekommen? Da alle gemeinsam genutzten Objekte und Textabschnitte, die ein Prozess verwendet (in diesem Beispiel der Compiler), nicht besonders interessant sind. Sie sind ein ständiger Aufwand für einen Prozess. In der Tat sind nachfolgende Aufrufe des Prozesses fast "kostenlos".

Vergleichen und kontrastieren Sie auch Folgendes:

MMAP () eine 1 GB-Datei. Ihre VMSize beträgt 1 + GB. Die Größe der residenten Gruppe besteht jedoch nur aus den Teilen der Datei, in denen Sie eine Auslagerung verursacht haben (indem Sie einen Zeiger auf diesen Bereich dereferenzieren). Und wenn Sie die gesamte Datei "lesen", hat der Kernel bis zum Ende möglicherweise bereits die Anfänge ausgelagert (dies ist einfach, da der Kernel genau weiß, wie / wo diese Seiten zu ersetzen sind, wenn sie erneut dereferenziert werden ). In beiden Fällen sind weder VMSize noch RSS ein guter Indikator für die "Speichernutzung". Sie haben tatsächlich nichts malloc () 'ed.

Im Gegensatz dazu Malloc () und berühren Sie VIELEN Speicher - bis Ihr Speicher auf die Festplatte ausgelagert wird. Der zugewiesene Speicher überschreitet jetzt Ihren RSS-Wert. Hier könnte Ihr VMSize Ihnen etwas mitteilen (Ihr Prozess verfügt über mehr Speicher, als sich tatsächlich in Ihrem RAM befindet). Es ist jedoch immer noch schwierig, zwischen freigegebenen VM-Seiten und vertauschten VM-Daten zu unterscheiden.

Hier wird Valgrind / Massif interessant. Es zeigt Ihnen, was Sie absichtlich zugewiesen haben (unabhängig vom Status Ihrer Seiten).


Ich habe eine Frage an dich. Ich habe einen Prozess, der mlock () alle seine MMAP-Dateien. Gibt es eine Möglichkeit zu bestimmen, wie viel dieses Speichers aktiv genutzt wird - wie viel davon wurde beispielsweise in den letzten ein oder zwei Minuten gelesen oder beschrieben?
Michael Martinez

2

Versuchen Sie Folgendes: Sie erhalten den gesamten RAM, der von allen in MB ausgeführten Prozessen tatsächlich verwendet wird

ps -eo size,pid,user,command --sort -size | awk '
  { hr=$1/1024 ; printf("%13.2f Mb ",hr) } 
  { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }
  ' | awk '{total=total + $1} END {print total}'

Das von sizegemeldete pshat wenig Bezug zur tatsächlichen Speichernutzung. Es ist die virtuelle Größe jedes Prozesses, der nicht unbedingt Speicher zugewiesen wird. Einige Segmente, die zugeordnet sind, sind ebenfalls nicht enthalten.
Matt

-2

Es zeigt Ihnen, wie viel Speicher Benutzer für Benutzer verwenden.

#!/bin/bash
total_mem=0

printf "%-10s%-10s\n" User MemUsage

while read u m
do
        [[ $old_user != $u ]] && {  printf "%-10s%-0.1f\n" $old_user $total_mem;
                                    total_mem=0; }
        total_mem="$(echo $m + $total_mem | bc)"
        old_user=$u

done < <(ps --no-headers -eo user,%mem| sort -k1)

#EOF

-3

Verwenden Sie diesen Befehl, um die Speicherauslastung in% zu ermitteln.

Speicher belegt:

grep Mem | awk '{print $3/$2 * 100.0}'

freier Speicher

grep Mem | awk '{print $4/$2 * 100.0}'

3
Ähm, das macht nichts. grepwerde nur dort sitzen und auf eine Eingabe warten.
Mattdm

1
Dies sollte seinfree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus
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.