Prawidłowo określające użycie pamięci w systemie Linux


63

Jestem trochę zdezorientowany niektórymi wynikami, które widzę z ps i za darmo .

Na moim serwerze jest to wynik 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

Rozumiem, w jaki sposób Linux zarządza pamięcią, dlatego, że zapisze użycie dysku w pamięci RAM, aby każdy kolejny dostęp był szybszy. Uważam, że wskazują na to „buforowane” kolumny. Ponadto różne bufory są przechowywane w pamięci RAM, wskazane w kolumnie „bufory”.

Więc jeśli dobrze rozumiem, „faktyczne” użycie powinno być „użytą” wartością „- / + buffers / cache” lub 561 w tym przypadku.

Więc zakładając, że wszystko jest poprawne, tym, co mnie rzuca, są wyniki ps aux.

Moje rozumienie pswyników polega na tym, że szósta kolumna (RSS) reprezentuje rozmiar w kilobajtach wykorzystywany przez proces do pamięci.

Kiedy uruchamiam to polecenie:

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

Czy nie powinna wynikać kolumna „używana” z „- / + bufory / pamięć podręczna” free -m?

Jak więc właściwie określić zużycie pamięci przez proces w systemie Linux? Najwyraźniej moja logika jest wadliwa.


To pytanie jest dość popularne i myślę, że powinienem podzielić się odpowiedzią htopautora na jedno podobne pytanie, które miałem poprzedniego dnia ... Jak obliczyć zużycie pamięci z / proc / meminfo (jak htop)
tgogos

Odpowiedzi:


57

Ta dokładna samo pytanie zadano na ServerFault właśnie drugi dzień :-)

System wirtualnej pamięci linux nie jest taki prosty. Nie możesz po prostu zsumować wszystkich pól RSS i otrzymać wartości zgłoszonej usedprzez free. Jest wiele powodów, ale uderzę w kilka największych.

  • Gdy proces rozwiąże się, zarówno rodzic, jak i dziecko będą wyświetlać ten sam kanał RSS. Jednak Linux używa copy-on-writetak, że oba procesy naprawdę wykorzystują tę samą pamięć. Tylko wtedy, gdy jeden z procesów zmodyfikuje pamięć, zostanie ona faktycznie skopiowana. To spowoduje, że freeliczba będzie mniejsza niż topsuma RSS.

  • Wartość RSS nie obejmuje pamięci współdzielonej. Ponieważ pamięć współdzielona nie jest własnością żadnego procesu, topnie jest uwzględniana w RSS. To spowoduje, że freeliczba będzie większa niż topsuma RSS.


1
To najlepsza odpowiedź, jaką do tej pory uzyskałem na dowolnej stronie wymiany stosów. A konkretnie to, co chciałem wiedzieć. Jest to szczególnie dokładne w mojej sytuacji, ponieważ mam do czynienia z programem, który napisałem, który rozwidla procesy, ale większość miejsca zajmuje biblioteki, których używają.
GoldenNewby

Problem z tą odpowiedzią polega na tym, że obliczenie sumy RSS i SHR często daje o wiele mniej niż wykorzystaną pamięć. Na przykład na VPS, który mam, używana pamięć wynosi 380 MB, a suma wszystkich danych RSS i SHR wynosi 90 MB.
user239558

2
@ user239558 Jak wspomniałem w odpowiedzi, istnieje wiele powodów, dla których liczby się nie sumują, wymieniłem tylko 2 z nich. Istnieje wiele innych liczb; pamięć podręczna, płyta, ogromne strony itp.
Patrick

2
Prawdopodobnie lata później po tym, jak odpowiedziałeś na to pytanie, nadal mam (przynajmniej) jedno zamieszanie. Powiedziałeś, że wartość RSS nie obejmuje pamięci współużytkowanej, ale ta odpowiedź brzmi : „Obejmuje pamięć z bibliotek współdzielonych, o ile strony z tych bibliotek są rzeczywiście w pamięci”. Teraz nie wiem, w co wierzyć ... Może brakuje mi tutaj subtelnych różnic ...
Naitree,

1
@Naitree „Shared Libraries”! = „Shared Memory”. pamięć współdzielona to takie jak shmgetlub mmap. Sformułowanie wokół pamięci jest bardzo trudne. Użycie niewłaściwego słowa w niewłaściwym miejscu może całkowicie zepsuć znaczenie zdania.
Patrick,

30

Jeśli szukasz numerów pamięci, które się sumują, spójrz na smem :

smem to narzędzie, które może przekazywać liczne raporty dotyczące wykorzystania pamięci w systemach Linux. W przeciwieństwie do istniejących narzędzi, smem może raportować proporcjonalny rozmiar zestawu (PSS), który jest bardziej znaczącym odzwierciedleniem ilości pamięci używanej przez biblioteki i aplikacje w systemie pamięci wirtualnej.

Ponieważ duże części pamięci fizycznej są zwykle współużytkowane przez wiele aplikacji, standardowa miara zużycia pamięci znana jako rozmiar zestawu rezydentnego (RSS) znacznie zawyża wykorzystanie pamięci. Zamiast tego PSS mierzy „sprawiedliwy udział” każdej aplikacji w każdym wspólnym obszarze, aby uzyskać realistyczny pomiar.

Na przykład tutaj:

# 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 

Podobnie PSSinteresująca kolumna, ponieważ uwzględnia pamięć współdzieloną.
W przeciwieństwie do RSStego sensowne jest sumowanie. Otrzymujemy tutaj 654 Mb ogółem dla procesów dotyczących obszarów użytkownika.

Dane wyjściowe z całego systemu mówią o reszcie:

# 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 

Tak więc 1 GB pamięci RAM ogółem = 654 Mb procesów użytkownika + 346 MB pamięci jądra + 16 MB wolnych
(daj lub weź kilka Mb)

Ogólnie pamięć podręczna zajmuje około połowy pamięci (494 Mb).

Dodatkowe pytanie : czym jest tutaj pamięć podręczna użytkownika a pamięć podręczna jądra?


btw dla czegoś wizualnego spróbuj:

# smem  --pie=name

wprowadź opis zdjęcia tutaj


14

Naprawdę dobrym narzędziem jest pmaplista bieżącego wykorzystania pamięci dla określonego procesu:

pmap -d PID

Aby uzyskać więcej informacji na ten temat, zobacz stronę podręcznika man, man pmapa także zapoznaj się z 20 narzędziami do monitorowania systemu Linux , które powinien znać każdy SysAdmin , które listy świetnych narzędzi zawsze używam do uzyskania informacji o moim Linux-ie.


To całkiem fajne narzędzie, ale tak naprawdę nie rozwiązuje mojego problemu. Próbuję dowiedzieć się, jak skutecznie określić „rzeczywiste” użycie pamięci na serwerze.
GoldenNewby

3
@GoldenNewby Nie istnieje coś takiego jak „faktyczne” wykorzystanie pamięci przez proces. Rzeczywiste wykorzystanie pamięci przez system jest tym, co freemówi.
Gilles

pmap -x PIDzawiera również kolumnę RSS, która często jest dość przydatna, aby dowiedzieć się, skąd pochodzi suma RSS procesu (jak zaobserwowano np. via top).
maxschlepzig

10

Uruchom na górze, kliknij, haby uzyskać pomoc, a następnie fdodaj pola. możesz dodać następujące pola:

  • RSS ilość pamięci fizycznej, z której korzysta aplikacja
  • CODE całkowita ilość pamięci używanej przez kod wykonywalny procesu
  • DATA - całkowita ilość pamięci (kb) przeznaczona na dane procesu i stos

Pomiędzy tymi 3 powinieneś mieć całkiem dokładne wyniki. Możesz także użyć bardziej szczegółowych zamienników dla top polecam htoplub atop.

Edycja: Prawie zapomniałem, jeśli chcesz naprawdę szczegółowych informacji. Znajdź PID i cat następujący plik.

PID=123

cat /proc/123/status

Edycja 2: Jeśli możesz go znaleźć lub mieć książkę:

Optymalizacja wydajności systemu Linux: praktyczny przewodnik po narzędziach wydajności systemu Linux

- zawiera sekcję Rozdział 5: Narzędzia wydajności: Pamięć specyficzna dla procesu - zawiera znacznie więcej informacji, niż byś chciał.


Cóż, domyślnie top ma rozmiar RSS procesu. Top daje identyczne wyniki, jak „ps aux” w moim przykładzie. Moje pytanie brzmi: w jaki sposób łączna wartość RSS wszystkich procesów jest znacznie wyższa niż „aktywne” użycie pamięci na całym serwerze?
GoldenNewby

5

psdaje ilość pamięci używanej przez każdy proces. Część tej pamięci to pliki zmapowane, które są uwzględniane w pamięci podręcznej. Część tej pamięci (zwłaszcza kodu) jest współdzielona z innymi procesami, więc jeśli dodasz wartości RSS, jest liczona wiele razy.

Nie ma właściwej odpowiedzi na pytanie „ile pamięci zajmuje ten proces?”, Ponieważ nie zależy to od samego procesu, zależy również od środowiska. Istnieje wiele różnych wartości, które możesz nazwać „zużyciem pamięci” w procesie, i nie pasują one do siebie ani się nie sumują, ponieważ liczą różne rzeczy.


4

Jak inni słusznie zauważyli, trudno jest uzyskać kontrolę nad rzeczywistą pamięcią używaną przez proces, co ze współdzielonymi regionami i plikami mmap i tym podobne.

Jeśli jesteś eksperymentatorem, możesz uruchomić valgrind i masyw . Może to być nieco ciężkie dla zwykłego użytkownika, ale z czasem zorientujesz się, jak zachowuje się pamięć aplikacji. Jeśli malloc () aplikacji jest dokładnie tym, czego potrzebuje, to da ci dobrą reprezentację rzeczywistego dynamicznego wykorzystania pamięci przez proces. Ale ten eksperyment można „zatruć”.

Aby komplikować sprawy, Linux pozwala przesadzić z pamięcią. Kiedy robisz pamięć malloc (), deklarujesz zamiar wykorzystania pamięci. Ale tak naprawdę alokacja nie następuje, dopóki nie zapiszesz bajtu na nowej stronie przydzielonej „pamięci RAM”. Możesz to sobie udowodnić, pisząc i uruchamiając mały program w taki sposób:

// 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 $!

Uruchom to na maszynie z mniej niż 16 GB pamięci RAM i, voila !, właśnie zdobyłeś 16 GB pamięci! (nie, nie bardzo).

Zauważ, topże widzisz „VIRT” jako 16,004G, ale% MEM to 0,0

Uruchom to ponownie z valgrind:

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

A masyw mówi „suma wszystkich allocs () = 16 GB”. To nie jest bardzo interesujące.

ALE, jeśli uruchomisz go przy zdrowym procesie:

# 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

I tutaj widzimy (bardzo empirycznie iz dużą pewnością), że kompilator przydzielił 77 KB sterty.

Po co tak bardzo starać się o wykorzystanie sterty? Ponieważ wszystkie współdzielone obiekty i sekcje tekstowe używane przez proces (w tym przykładzie kompilator) nie są strasznie interesujące. Są stałym kosztem procesu. W rzeczywistości kolejne wywołania tego procesu niemal przychodzą „za darmo”.

Porównaj i porównaj następujące elementy:

MMAP () plik 1 GB. Twój VMSize będzie wynosił 1 + GB. Ale Twój Resident Set Size będzie tylko częściami pliku, w którym spowodowałeś utworzenie stronicowania (poprzez usunięcie odniesienia wskaźnika do tego regionu). A jeśli „przeczytasz” cały plik, to zanim dojdziesz do końca, jądro mogło już wygenerować strony początkowe (jest to łatwe, ponieważ jądro dokładnie wie, jak / gdzie zamienić te strony, jeśli ponownie się wyrejestrujesz) ). W obu przypadkach ani VMSize, ani RSS nie są dobrym wskaźnikiem „zużycia” pamięci. Tak naprawdę nic nie edytowałeś w malloc ().

Natomiast Malloc () i dotknij DUŻO pamięci - aż pamięć zostanie zamieniona na dysk. Zatem przydzielona pamięć przekracza teraz wartość RSS. Tutaj twój VMSize może zacząć ci coś mówić (twój proces ma więcej pamięci niż to, co faktycznie znajduje się w twojej pamięci RAM). Ale nadal trudno jest odróżnić maszynę wirtualną, która jest stronami udostępnionymi, i maszynę wirtualną, która zamienia dane.

To właśnie tutaj interesuje się valgrind / masyw. Pokazuje, co celowo przydzieliłeś (niezależnie od stanu twoich stron).


Mam do ciebie pytanie Mam proces, w którym mlock () s wszystkie pliki mmap. Czy istnieje sposób na określenie, ile z tej pamięci jest aktywnie wykorzystywane - ile z niej zostało odczytane lub zapisane w, powiedzmy, w ostatniej minucie lub dwóch?
Michael Martinez,

2

Spróbuj tego: da ci całkowitą pamięć RAM faktycznie używaną przez cały proces działający w MB

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}'

sizeDonosi psma niewiele wspólnego z rzeczywistym wykorzystaniu pamięci. Jest to wirtualny rozmiar każdego procesu, który niekoniecznie musi mieć przydzieloną pamięć. Nie obejmuje również niektórych przydzielonych segmentów.
Matt

-2

Pokaże, ile użytkowników pamięci przez użytkowników ..

#!/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

Użyj tego polecenia, aby znaleźć wykorzystanie pamięci w%.

Wykorzystana pamięć:

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

wolna pamięć

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

3
Errr, to nic nie da. greppo prostu usiądę i czekam na dane wejściowe.
mattdm,

1
Powinno to byćfree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.