Jak zmierzyć faktyczne wykorzystanie pamięci przez aplikację lub proces?


712

To pytanie jest szczegółowo omówione tutaj .

Jak mierzysz wykorzystanie pamięci przez aplikację lub proces w systemie Linux?

Z artykułu blogu Zrozumienia wykorzystania pamięci w systemie Linux , psnie jest dokładnym narzędziem do wykorzystania dla tej intencji.

Dlaczego ps„źle”

W zależności od tego, jak na to patrzysz, psnie zgłasza rzeczywistego wykorzystania pamięci przez procesy. W rzeczywistości pokazuje, ile prawdziwej pamięci zajmie każdy proces, gdyby był jedynym uruchomionym procesem . Oczywiście w typowej maszynie z Linuksem w danym momencie działa kilkadziesiąt procesów, co oznacza, że ​​zgłoszone numery VSZ i RSS pssą prawie zdecydowanie błędne .


6
To pytanie prawdopodobnie należy obecnie do serverfault.com, choć mówi mi, że jest „za stary, aby przeprowadzić migrację”. Ale tak naprawdę nie chcę go zamykać ...
thomasrutter,


2
Właściwie psnawet tego nie pokazuje - pokazuje numery pamięci wirtualnej i rezydentnej, gdzie wirtualna to maksymalna ilość pamięci, którą proces teoretycznie mógłby z niej skorzystać, był to jedyny proces (nigdy nie), używany na każdej przydzielonej stronie (nigdy się nie zdarza) i nie mapował ani nie mapował żadnych stron (mało prawdopodobne). Podczas gdy rezydent pokazuje, ile pamięci wirtualnej jest obecnie zamapowane na fizyczną. Zazwyczaj virt > usage > resjednak w systemie 64-bitowym virt ~= res*10jest to bardzo szeroki zakres.
Dima Tisnek,

5
Fragment połączonego artykułu jest całkowitym nonsensem. RSS to faktycznie używana pamięć fizyczna, a VSZ może, ale nie musi, przekładać się na użycie pamięci fizycznej, nawet jeśli proces był jedyny.
David Schwartz

Odpowiedzi:


356

Za pomocą pslub podobnych narzędzi uzyskasz tylko tyle stron pamięci przydzielonych przez ten proces. Ta liczba jest poprawna, ale:

  • nie odzwierciedla faktycznej ilości pamięci używanej przez aplikację, tylko ilość pamięci zarezerwowanej dla niej

  • może wprowadzać w błąd, jeśli strony są współużytkowane, na przykład przez kilka wątków lub przy użyciu dynamicznie linkowanych bibliotek

Jeśli naprawdę chcesz wiedzieć, ile pamięci faktycznie używa Twoja aplikacja, musisz uruchomić ją w programie profilującym. Na przykład valgrindmoże dać ci wgląd w ilość używanej pamięci, a co ważniejsze, o możliwych wyciekach pamięci w twoim programie. Narzędzie do profilowania sterty valgrind nazywa się „masywem”:

Massif to profiler sterty. Wykonuje szczegółowe profilowanie sterty, wykonując regularne migawki sterty programu. Tworzy wykres przedstawiający zużycie sterty w czasie, zawierający informacje o tym, które części programu są odpowiedzialne za najwięcej przydziałów pamięci. Uzupełnieniem wykresu jest plik tekstowy lub HTML, który zawiera więcej informacji w celu ustalenia, gdzie przydzielana jest najwięcej pamięci. Massif uruchamia programy około 20 razy wolniej niż zwykle.

Jak wyjaśniono w dokumentacji valgrind , musisz uruchomić program poprzez valgrind:

valgrind --tool=massif <executable> <arguments>

Massif zapisuje zrzut migawek użycia pamięci (np massif.out.12345.). Zapewniają one (1) oś czasu wykorzystania pamięci, (2) dla każdej migawki, zapis miejsca w pamięci programu. Świetnym narzędziem graficznym do analizy tych plików jest wizualizator masywów . Okazało się jednak ms_print, że proste narzędzie tekstowe dostarczane wraz z valgrindem jest już bardzo pomocne.

Aby znaleźć wycieki pamięci, użyj (domyślnego) memchecknarzędzia valgrind.


44
Aby zinterpretować wyniki generowane przez valgrind, mogę polecić alleyoop. Nie jest to zbyt wymyślne i mówi po prostu, co musisz wiedzieć, aby znaleźć źródła wycieków. Ładna para narzędzi.
Dan

6
Pozycja (a) jest poprawna. Istnieje różnica między wykorzystanymi stronami a pamięcią faktycznie przydzieloną przez aplikację za pomocą wywołań funkcji malloc (), nowych itp. Wykorzystanie rezydenta pokazuje tylko, ile pamięci stronicowanej znajduje się w pamięci RAM.
jcoffland

63
To tak naprawdę nie mówi, jak uzyskać wykorzystanie pamięci za pomocą valgrind?
Matt Joiner

11
domyślne narzędzie valgrind, memcheck, jest przydatne do wykrywania wycieków pamięci, ale tak naprawdę nie jest profilerem pamięci. W tym celu chcesz valgrind --tool = masyw.
Todd Freed

3
@DavidSchwartz Nie rozumiem, w jaki sposób twoje oświadczenie zaprzecza mojemu. Mam wrażenie, że zbytnio martwisz się tym, że jestem „w błędzie”, niż czytając to, co mówię. Chodzi mi o to, że RSS jest niewłaściwym miernikiem rzeczywistego wykorzystania pamięci przez aplikację, a ty robisz to samo w dwóch ostatnich zdaniach. Naprawdę, co według ciebie było powodem, dla którego podniosłem skurcz RSS? Abyś przeliterował mi to, aby udowodnić, że jestem „w błędzie” dokładnie tym, o czym mówię? Twoje podejście do mnie jest męczące.
ypnos

280

Wypróbuj polecenie pmap :

sudo pmap -x <process pid>

45
uruchom z sudo lub nie powoduje błędu i nie zużywa pamięci.
Matt

22
Nie istnieje w OSX (dla każdego, kto przychodzi tutaj z Google)
jcollum

3
To pełna odpowiedź na pytanie! ps. W mojej powłoce pmap może odczytać proces bez sudo.
MasterControlProgram

7
W przypadku OS X (pozornie nie dotyczy OP), można zobaczyć podobne dane za pomocą vmmap (1)
jrg

uwaga: daje zupełnie inną odpowiedź niżgnome-system-monitor
ribamar,

190

Trudno powiedzieć na pewno, ale oto dwie „bliskie” rzeczy, które mogą pomóc.

$ ps aux 

da ci wirtualny rozmiar (VSZ)

Możesz także uzyskać szczegółowe statystyki z systemu plików / proc, przechodząc do /proc/$pid/status

Najważniejszy jest VmSize, który powinien być zbliżony do czego ps aux daje.

/ proc / 19420 $ status kota
Nazwa: firefox
Stan: S (spanie)
Tgid: 19420
Pid: 19420
PPid: 1
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
Rozmiar FDS: 256
Grupy: 4 6 20 24 25 29 30 44 46 107 109 115 124 1000 
VmPeak: 222956 kB
VmSize: 212520 kB
VmLck: 0 kB
VmHWM: 127912 kB
VmRSS: 118768 kB
VmData: 170180 kB
VmStk: 228 kB
VmExe: 28 kB
VmLib: 35424 kB
VmPTE: 184 kB
Wątki: 8
SigQ: 0/16382
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000020001000
SigCgt: 000000018000442f
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Cpus_allowed: 03
Mems_allowed: 1
dobrowolne przełączniki: 63422
przełączniki nieobowiązkowe: 7171


21
Czy coś brakuje? Pytanie brzmiało, jak lepiej zmierzyć zużycie pamięci przez proces, biorąc pod uwagę, że VSZ i RSS zgłaszane w ps są mylące. Twoja odpowiedź zawiera szczegółowe informacje na temat wyszukiwania VSZ - tej samej wartości, o której wspomniano, że wprowadza w błąd.
thomasrutter,

16
@ thomasrutter Tak, brakuje Ci oryginalnego pytania (wersja 1), zostało ono zredagowane kilka razy i jest dość stare (2008). Pierwotne pytanie dotyczyło tylko sposobu pomiaru zużycia pamięci przez proces. Jeśli jednak są nieaktualne, możesz edytować pytania i odpowiedzi. :)
DustinB

1
uwaga: daje zupełnie inną odpowiedź niżgnome-system-monitor
ribamar,

131

W najnowszych wersjach systemu Linux użyj podsystemu smaps . Na przykład dla procesu o PID 1234:

cat /proc/1234/smaps

Powie ci dokładnie, ile pamięci zużywa w tym czasie. Co ważniejsze, podzieli pamięć na prywatną i współużytkowaną, dzięki czemu możesz określić, ile pamięci używa Twoja instancja programu, bez uwzględniania pamięci współużytkowanej przez wiele instancji programu.


Chyba pmapjest to prostszy interfejs.
ribamar

126

Nie ma łatwego sposobu na obliczenie tego. Ale niektórzy próbowali uzyskać dobre odpowiedzi:


nice wyświetla czystą listę pamięci i procesu
Rubytastic

Bardzo ładne, z dość inteligentnym grupowaniem.
Rohmer

Tak, naprawdę całkiem miłe. Uważam ps_memi smembardzo przydatne dla środków użytkownika końcowego, podczas gdy np. pmapbardzo szczegółowe dane wyjściowe są ukierunkowane na devs ... pozwalają odzyskać użycie pamięci Firefox dla każdej czcionki, dodatku, biblioteki lib np. Dziękuję wszystkim exp. @Bash, @thomasruther.
tuk0z

ten jest jak dotąd jedynym, który pasuje do wynikugnome-system-monitor
ribamar

110

Użyj smem , który jest alternatywą dla ps, która oblicza USS i PSS na proces. To, czego chcesz, to prawdopodobnie PSS.

  • USS - Unikalny rozmiar zestawu. Jest to ilość niewspółdzielone pamięci unikalne dla tego sposobu (myśleć jak U o wyjątkowej pamięci). Nie obejmuje pamięci współdzielonej. Zatem ta wola pod -report ilość pamięci a zastosowania proces, ale jest przydatna, gdy chcesz ignorować pamięci współdzielonej.

  • PSS - Proporcjonalny rozmiar zestawu. To jest to, czego chcesz. Dodaje do siebie unikalną pamięć (USS) oraz część pamięci współdzielonej podzieloną przez liczbę procesów współużytkujących tę pamięć. W ten sposób uzyskasz dokładną reprezentację ilości faktycznej pamięci fizycznej wykorzystywanej na proces - z pamięcią współdzieloną naprawdę reprezentowaną jako współdzielona. Pomyśl o P jako o pamięci fizycznej .

Jak to się porównuje do RSS, jak donosi ps i inne narzędzia:

  • RSS - Rozmiar zestawu rezydenta. Jest to ilość pamięci współużytkowanej plus pamięć nieudostępniona używana przez każdy proces. Jeśli jakikolwiek pamięci procesy zakładowego, będzie to ponad -report ilości pamięci faktycznie używany, ponieważ ta sama pamięć dzielona będą liczone więcej niż raz - pojawia się ponownie w każdym innym procesie, że akcje tej samej pamięci. Dlatego jest dość zawodny, szczególnie gdy procesy o wysokiej pamięci mają wiele rozwidleń - co jest powszechne na serwerze, z takimi procesami jak Apache lub PHP (fastcgi / FPM).

Uwaga: smem może również (opcjonalnie) generować wykresy, takie jak wykresy kołowe i tym podobne. IMO nie potrzebujesz tego. Jeśli chcesz go używać z wiersza poleceń, tak jak możesz użyć ps -A v, nie musisz instalować zalecanej zależności python-matplotlib.


2
Jednym z krytycznych punktów na temat RSS jest to, że obecnie większość aplikacji udostępnia wiele stron kodowych. Każda biblioteka współdzielona (np. Libc i libstdc ++) będzie liczona dla każdego procesu, który z niej korzysta. A jeśli uruchomionych jest wiele instancji procesu, cały ten kod zostanie policzony podwójnie.
David C.

1
Właśnie dlatego RSS przesadza pod względem faktycznej pamięci fizycznej na proces.
thomasrutter

3
smem jest tym, czego potrzebowałem. Uruchamiając go z -t za każdym razem, gdy uruchamiam nową instancję procesu, widzę pamięć zużywaną przez każdą instancję. Dla chrome: smem -t -P '/ opt / google / chrome'
xtian

Trudno mi znaleźć dokumentację dla smem .. czy domyślnie wyświetla dane w bajtach, kilobajtach lub megabajtach?
ZN13

4
TL; DR: USS = Ilość pamięci fizycznej, która zostanie zwolniona, jeśli proces zostanie zabity, PSS = Ilość pamięci fizycznej, której ten proces potrzebuje z systemu, jeśli nie zostaną zabite żadne istniejące procesy, RSS = Ilość pamięci fizycznej, która jest dostępna dla ten proces (ale nie zawsze wyłączny dostęp).
Mikko Rantalainen

95
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 "" }' |\
    cut -d "" -f2 | cut -d "-" -f1

Użyj tego jako root, a każdy proces uzyska wyraźny wynik wykorzystania pamięci.

PRZYKŁAD WYJŚCIA:

     0.00 Mb COMMAND 
  1288.57 Mb /usr/lib/firefox
   821.68 Mb /usr/lib/chromium/chromium 
   762.82 Mb /usr/lib/chromium/chromium 
   588.36 Mb /usr/sbin/mysqld 
   547.55 Mb /usr/lib/chromium/chromium 
   523.92 Mb /usr/lib/tracker/tracker
   476.59 Mb /usr/lib/chromium/chromium 
   446.41 Mb /usr/bin/gnome
   421.62 Mb /usr/sbin/libvirtd 
   405.11 Mb /usr/lib/chromium/chromium 
   302.60 Mb /usr/lib/chromium/chromium 
   291.46 Mb /usr/lib/chromium/chromium 
   284.56 Mb /usr/lib/chromium/chromium 
   238.93 Mb /usr/lib/tracker/tracker
   223.21 Mb /usr/lib/chromium/chromium 
   197.99 Mb /usr/lib/chromium/chromium 
   194.07 Mb conky 
   191.92 Mb /usr/lib/chromium/chromium 
   190.72 Mb /usr/bin/mongod 
   169.06 Mb /usr/lib/chromium/chromium 
   155.11 Mb /usr/bin/gnome
   136.02 Mb /usr/lib/chromium/chromium 
   125.98 Mb /usr/lib/chromium/chromium 
   103.98 Mb /usr/lib/chromium/chromium 
    93.22 Mb /usr/lib/tracker/tracker
    89.21 Mb /usr/lib/gnome
    80.61 Mb /usr/bin/gnome
    77.73 Mb /usr/lib/evolution/evolution
    76.09 Mb /usr/lib/evolution/evolution
    72.21 Mb /usr/lib/gnome
    69.40 Mb /usr/lib/evolution/evolution
    68.84 Mb nautilus
    68.08 Mb zeitgeist
    60.97 Mb /usr/lib/tracker/tracker
    59.65 Mb /usr/lib/evolution/evolution
    57.68 Mb apt
    55.23 Mb /usr/lib/gnome
    53.61 Mb /usr/lib/evolution/evolution
    53.07 Mb /usr/lib/gnome
    52.83 Mb /usr/lib/gnome
    51.02 Mb /usr/lib/udisks2/udisksd 
    50.77 Mb /usr/lib/evolution/evolution
    50.53 Mb /usr/lib/gnome
    50.45 Mb /usr/lib/gvfs/gvfs
    50.36 Mb /usr/lib/packagekit/packagekitd 
    50.14 Mb /usr/lib/gvfs/gvfs
    48.95 Mb /usr/bin/Xwayland :1024 
    46.21 Mb /usr/bin/gnome
    42.43 Mb /usr/bin/zeitgeist
    42.29 Mb /usr/lib/gnome
    41.97 Mb /usr/lib/gnome
    41.64 Mb /usr/lib/gvfs/gvfsd
    41.63 Mb /usr/lib/gvfs/gvfsd
    41.55 Mb /usr/lib/gvfs/gvfsd
    41.48 Mb /usr/lib/gvfs/gvfsd
    39.87 Mb /usr/bin/python /usr/bin/chrome
    37.45 Mb /usr/lib/xorg/Xorg vt2 
    36.62 Mb /usr/sbin/NetworkManager 
    35.63 Mb /usr/lib/caribou/caribou 
    34.79 Mb /usr/lib/tracker/tracker
    33.88 Mb /usr/sbin/ModemManager 
    33.77 Mb /usr/lib/gnome
    33.61 Mb /usr/lib/upower/upowerd 
    33.53 Mb /usr/sbin/gdm3 
    33.37 Mb /usr/lib/gvfs/gvfsd
    33.36 Mb /usr/lib/gvfs/gvfs
    33.23 Mb /usr/lib/gvfs/gvfs
    33.15 Mb /usr/lib/at
    33.15 Mb /usr/lib/at
    30.03 Mb /usr/lib/colord/colord 
    29.62 Mb /usr/lib/apt/methods/https 
    28.06 Mb /usr/lib/zeitgeist/zeitgeist
    27.29 Mb /usr/lib/policykit
    25.55 Mb /usr/lib/gvfs/gvfs
    25.55 Mb /usr/lib/gvfs/gvfs
    25.23 Mb /usr/lib/accountsservice/accounts
    25.18 Mb /usr/lib/gvfs/gvfsd 
    25.15 Mb /usr/lib/gvfs/gvfs
    25.15 Mb /usr/lib/gvfs/gvfs
    25.12 Mb /usr/lib/gvfs/gvfs
    25.10 Mb /usr/lib/gnome
    25.10 Mb /usr/lib/gnome
    25.07 Mb /usr/lib/gvfs/gvfsd 
    24.99 Mb /usr/lib/gvfs/gvfs
    23.26 Mb /usr/lib/chromium/chromium 
    22.09 Mb /usr/bin/pulseaudio 
    19.01 Mb /usr/bin/pulseaudio 
    18.62 Mb (sd
    18.46 Mb (sd
    18.30 Mb /sbin/init 
    18.17 Mb /usr/sbin/rsyslogd 
    17.50 Mb gdm
    17.42 Mb gdm
    17.09 Mb /usr/lib/dconf/dconf
    17.09 Mb /usr/lib/at
    17.06 Mb /usr/lib/gvfs/gvfsd
    16.98 Mb /usr/lib/at
    16.91 Mb /usr/lib/gdm3/gdm
    16.86 Mb /usr/lib/gvfs/gvfsd
    16.86 Mb /usr/lib/gdm3/gdm
    16.85 Mb /usr/lib/dconf/dconf
    16.85 Mb /usr/lib/dconf/dconf
    16.73 Mb /usr/lib/rtkit/rtkit
    16.69 Mb /lib/systemd/systemd
    13.13 Mb /usr/lib/chromium/chromium 
    13.13 Mb /usr/lib/chromium/chromium 
    10.92 Mb anydesk 
     8.54 Mb /sbin/lvmetad 
     7.43 Mb /usr/sbin/apache2 
     6.82 Mb /usr/sbin/apache2 
     6.77 Mb /usr/sbin/apache2 
     6.73 Mb /usr/sbin/apache2 
     6.66 Mb /usr/sbin/apache2 
     6.64 Mb /usr/sbin/apache2 
     6.63 Mb /usr/sbin/apache2 
     6.62 Mb /usr/sbin/apache2 
     6.51 Mb /usr/sbin/apache2 
     6.25 Mb /usr/sbin/apache2 
     6.22 Mb /usr/sbin/apache2 
     3.92 Mb bash 
     3.14 Mb bash 
     2.97 Mb bash 
     2.95 Mb bash 
     2.93 Mb bash 
     2.91 Mb bash 
     2.86 Mb bash 
     2.86 Mb bash 
     2.86 Mb bash 
     2.84 Mb bash 
     2.84 Mb bash 
     2.45 Mb /lib/systemd/systemd
     2.30 Mb (sd
     2.28 Mb /usr/bin/dbus
     1.84 Mb /usr/bin/dbus
     1.46 Mb ps 
     1.21 Mb openvpn hackthebox.ovpn 
     1.16 Mb /sbin/dhclient 
     1.16 Mb /sbin/dhclient 
     1.09 Mb /lib/systemd/systemd 
     0.98 Mb /sbin/mount.ntfs /dev/sda3 /media/n0bit4/Data 
     0.97 Mb /lib/systemd/systemd 
     0.96 Mb /lib/systemd/systemd 
     0.89 Mb /usr/sbin/smartd 
     0.77 Mb /usr/bin/dbus
     0.76 Mb su 
     0.76 Mb su 
     0.76 Mb su 
     0.76 Mb su 
     0.76 Mb su 
     0.76 Mb su 
     0.75 Mb sudo su 
     0.75 Mb sudo su 
     0.75 Mb sudo su 
     0.75 Mb sudo su 
     0.75 Mb sudo su 
     0.75 Mb sudo su 
     0.74 Mb /usr/bin/dbus
     0.71 Mb /usr/lib/apt/methods/http 
     0.68 Mb /bin/bash /usr/bin/mysqld_safe 
     0.68 Mb /sbin/wpa_supplicant 
     0.66 Mb /usr/bin/dbus
     0.61 Mb /lib/systemd/systemd
     0.54 Mb /usr/bin/dbus
     0.46 Mb /usr/sbin/cron 
     0.45 Mb /usr/sbin/irqbalance 
     0.43 Mb logger 
     0.41 Mb awk { hr=$1/1024 ; printf("%13.2f Mb ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" } 
     0.40 Mb /usr/bin/ssh
     0.34 Mb /usr/lib/chromium/chrome
     0.32 Mb cut 
     0.32 Mb cut 
     0.00 Mb [kthreadd] 
     0.00 Mb [ksoftirqd/0] 
     0.00 Mb [kworker/0:0H] 
     0.00 Mb [rcu_sched] 
     0.00 Mb [rcu_bh] 
     0.00 Mb [migration/0] 
     0.00 Mb [lru
     0.00 Mb [watchdog/0] 
     0.00 Mb [cpuhp/0] 
     0.00 Mb [cpuhp/1] 
     0.00 Mb [watchdog/1] 
     0.00 Mb [migration/1] 
     0.00 Mb [ksoftirqd/1] 
     0.00 Mb [kworker/1:0H] 
     0.00 Mb [cpuhp/2] 
     0.00 Mb [watchdog/2] 
     0.00 Mb [migration/2] 
     0.00 Mb [ksoftirqd/2] 
     0.00 Mb [kworker/2:0H] 
     0.00 Mb [cpuhp/3] 
     0.00 Mb [watchdog/3] 
     0.00 Mb [migration/3] 
     0.00 Mb [ksoftirqd/3] 
     0.00 Mb [kworker/3:0H] 
     0.00 Mb [kdevtmpfs] 
     0.00 Mb [netns] 
     0.00 Mb [khungtaskd] 
     0.00 Mb [oom_reaper] 
     0.00 Mb [writeback] 
     0.00 Mb [kcompactd0] 
     0.00 Mb [ksmd] 
     0.00 Mb [khugepaged] 
     0.00 Mb [crypto] 
     0.00 Mb [kintegrityd] 
     0.00 Mb [bioset] 
     0.00 Mb [kblockd] 
     0.00 Mb [devfreq_wq] 
     0.00 Mb [watchdogd] 
     0.00 Mb [kswapd0] 
     0.00 Mb [vmstat] 
     0.00 Mb [kthrotld] 
     0.00 Mb [ipv6_addrconf] 
     0.00 Mb [acpi_thermal_pm] 
     0.00 Mb [ata_sff] 
     0.00 Mb [scsi_eh_0] 
     0.00 Mb [scsi_tmf_0] 
     0.00 Mb [scsi_eh_1] 
     0.00 Mb [scsi_tmf_1] 
     0.00 Mb [scsi_eh_2] 
     0.00 Mb [scsi_tmf_2] 
     0.00 Mb [scsi_eh_3] 
     0.00 Mb [scsi_tmf_3] 
     0.00 Mb [scsi_eh_4] 
     0.00 Mb [scsi_tmf_4] 
     0.00 Mb [scsi_eh_5] 
     0.00 Mb [scsi_tmf_5] 
     0.00 Mb [bioset] 
     0.00 Mb [kworker/1:1H] 
     0.00 Mb [kworker/3:1H] 
     0.00 Mb [kworker/0:1H] 
     0.00 Mb [kdmflush] 
     0.00 Mb [bioset] 
     0.00 Mb [kdmflush] 
     0.00 Mb [bioset] 
     0.00 Mb [jbd2/sda5
     0.00 Mb [ext4
     0.00 Mb [kworker/2:1H] 
     0.00 Mb [kauditd] 
     0.00 Mb [bioset] 
     0.00 Mb [drbd
     0.00 Mb [irq/27
     0.00 Mb [i915/signal:0] 
     0.00 Mb [i915/signal:1] 
     0.00 Mb [i915/signal:2] 
     0.00 Mb [ttm_swap] 
     0.00 Mb [cfg80211] 
     0.00 Mb [kworker/u17:0] 
     0.00 Mb [hci0] 
     0.00 Mb [hci0] 
     0.00 Mb [kworker/u17:1] 
     0.00 Mb [iprt
     0.00 Mb [iprt
     0.00 Mb [kworker/1:0] 
     0.00 Mb [kworker/3:0] 
     0.00 Mb [kworker/0:0] 
     0.00 Mb [kworker/2:0] 
     0.00 Mb [kworker/u16:0] 
     0.00 Mb [kworker/u16:2] 
     0.00 Mb [kworker/3:2] 
     0.00 Mb [kworker/2:1] 
     0.00 Mb [kworker/1:2] 
     0.00 Mb [kworker/0:2] 
     0.00 Mb [kworker/2:2] 
     0.00 Mb [kworker/0:1] 
     0.00 Mb [scsi_eh_6] 
     0.00 Mb [scsi_tmf_6] 
     0.00 Mb [usb
     0.00 Mb [bioset] 
     0.00 Mb [kworker/3:1] 
     0.00 Mb [kworker/u16:1] 

1
Czy jest jakiś sposób na filtrowanie listy, aby mieć procesy, które używają więcej niż powiedzmy 25% pamięci na powiedzmy 30s? Próbuję zobaczyć uciekające procesy, takie jak przeglądarka Chrome podczas korzystania z debugera PHPEclipse.
Stephane

ten filtr byłby niesamowity
aleix

1
Wyślę to tak szybko, jak to możliwe.
Lokendra Singh Rawat

2
Świetny! Ale pętla powinna zaczynać się od x=2wyjścia pid i użytkownika.
Boris Brodski

70

Co time?

Nie Bash wbudowane timeale można znaleźć z which time, na przykład/usr/bin/time

Oto, co obejmuje, na prostym ls:

$ /usr/bin/time --verbose ls
(...)
Command being timed: "ls"
User time (seconds): 0.00
System time (seconds): 0.00
Percent of CPU this job got: 0%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 2372
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 121
Voluntary context switches: 2
Involuntary context switches: 9
Swaps: 0
File system inputs: 256
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

Ja również. W ten sposób profiluję zadania w powercron.eu :)
Moonchild

5
brew install gnu-timeużyj, gtimejeśli korzystasz z systemu macOS.
Nobu,

4
Wada: nie otrzyma wyników, dopóki proces nie zakończy się jego wykonanie. Nie można go używać do monitorowania uruchomionego procesu w czasie rzeczywistym.
Makesh

/ usr / bin / time -f '% M'
infomaniac

1
Możesz go również wywołać przy użyciu \ time (z odwrotnym ukośnikiem, aby zapobiec użyciu wewnętrznego czasu powłoki).
Raúl Salinas-Monteagudo

39

To doskonałe podsumowanie narzędzi i problemów: link archive.org

Zacytuję to, aby więcej deweloperów faktycznie to przeczytało.

Jeśli chcesz przeanalizować wykorzystanie pamięci przez cały system lub dokładnie przeanalizować wykorzystanie pamięci przez jedną aplikację (nie tylko użycie sterty), skorzystaj z exmap . W przypadku analizy całego systemu, znajdź procesy o najwyższym efektywnym użyciu, zajmują najwięcej pamięci w praktyce, znajdź procesy o najwyższym możliwym do zapisu użyciu, tworzą najwięcej danych (a zatem prawdopodobnie wyciekają lub są bardzo nieefektywne w wykorzystaniu danych). Wybierz taką aplikację i przeanalizuj jej mapowania w drugim widoku listy. Aby uzyskać więcej informacji, zobacz sekcję exmap. Użyj także xrestop, aby sprawdzić wysokie zużycie zasobów X, szczególnie jeśli proces serwera X zajmuje dużo pamięci. Szczegóły w sekcji xrestop.

Jeśli chcesz wykryć wycieki, użyj valgrind lub ewentualnie kmtrace .

Jeśli chcesz przeanalizować użycie sterty (malloc itp.) Aplikacji, uruchom ją w memprof lub za pomocą kmtrace , profiluj aplikację i przeszukaj drzewo wywołań funkcji w poszukiwaniu największych alokacji. Zobacz ich sekcje, aby uzyskać więcej informacji.


28

Oprócz rozwiązań wymienionych w twoich odpowiedziach możesz użyć polecenia Linux „top”; Zapewnia dynamiczny widok działającego systemu w czasie rzeczywistym, podaje użycie procesora i pamięci dla całego systemu wraz z każdym programem, w procentach:

top

aby filtrować według pid programu:

top -p <PID>

aby filtrować według nazwy programu:

top | grep <PROCESS NAME>

„góra” zawiera także niektóre pola, takie jak:

VIRT - Virtual Image (kb): Całkowita ilość pamięci wirtualnej wykorzystywanej przez zadanie

RES - rozmiar rezydenta (kb): niezmieniona pamięć fizyczna, z której korzystało zadanie; RES = KOD + DANE.

DANE - Dane + Rozmiar stosu (kb): Ilość pamięci fizycznej przeznaczona na kod inny niż wykonywalny, znany również jako rozmiar „zestawu rezydentów danych” lub DRS.

SHR - Rozmiar pamięci współdzielonej (kb): Ilość pamięci współdzielonej wykorzystywanej przez zadanie. Po prostu odzwierciedla pamięć, którą można potencjalnie współdzielić z innymi procesami.

Odnośnik tutaj .


20

Nie ma na to ani jednej odpowiedzi, ponieważ nie można dokładnie określić ilości pamięci używanej przez proces. Większość procesów w systemie Linux używa bibliotek współdzielonych. Załóżmy na przykład, że chcesz obliczyć zużycie pamięci dla procesu „ls”. Czy liczysz tylko pamięć używaną przez wykonywalne „ls” (jeśli możesz ją wydzielić)? Co powiesz na libc? Lub wszystkie te inne biblioteki lib, które są wymagane do uruchomienia „ls”?

linux-gate.so.1 =>  (0x00ccb000)
librt.so.1 => /lib/librt.so.1 (0x06bc7000)
libacl.so.1 => /lib/libacl.so.1 (0x00230000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00162000)
libc.so.6 => /lib/libc.so.6 (0x00b40000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00cb4000)
/lib/ld-linux.so.2 (0x00b1d000)
libattr.so.1 => /lib/libattr.so.1 (0x00229000)
libdl.so.2 => /lib/libdl.so.2 (0x00cae000)
libsepol.so.1 => /lib/libsepol.so.1 (0x0011a000)

Można argumentować, że są one współużytkowane przez inne procesy, ale „ls” nie można uruchomić w systemie bez ich załadowania.

Ponadto, jeśli chcesz wiedzieć, ile pamięci potrzebuje proces do planowania wydajności, musisz obliczyć, ile zużywa każda dodatkowa kopia procesu. Myślę, że / proc / PID / status może dać ci wystarczającą ilość informacji o zużyciu pamięci. Z drugiej strony valgrind zapewni lepszy profil wykorzystania pamięci przez cały okres istnienia programu


Próbuję znaleźć, ile pamięci proces zajmuje na maszynie wirtualnej i chcę go użyć, aby ustawić limit pamięci w kubernetes, zgadzam się na tę odpowiedź, więc będę używać pamięci pokazanej przezpmap
Deepak Deore

16

Jeśli Twój kod jest w C lub C ++, możesz być w stanie go użyć getrusage() co zwróci różne statystyki dotyczące wykorzystania pamięci i czasu przez proces.

Nie wszystkie platformy obsługują to i zwrócą 0 wartości dla opcji użycia pamięci.

Zamiast tego możesz spojrzeć na plik wirtualny utworzony w /proc/[pid]/statm(gdzie [pid]jest zastąpiony identyfikatorem procesu. Możesz to uzyskać zgetpid() ).

Ten plik będzie wyglądał jak plik tekstowy z 7 liczbami całkowitymi. Prawdopodobnie najbardziej interesują Cię pierwsze (całe użycie pamięci) i szóste (użycie pamięci danych) liczby w tym pliku.


Pamiętaj, że nie jest to obsługiwane na wszystkich platformach.
CashCow

Według strony podręcznika systemu Linux ( linux.die.net/man/2/getrusage ), getrusage jest częścią specyfikacji SVr4, 4.3BSD i POSIX.1-2001 (zauważając, że POSIX określa tylko pola utime i stime). I nie spodziewałbym się, że będzie działał na platformach innych niż UNIX (może z wyjątkiem środowiska takiego jak Cygwin, które zapewnia możliwości UNIX dla innych platform).
David C.

@DavidC. OP pyta o Linuksa.
Alexis Wilke,

@CashCow, miałeś na myśli getpid(), ponieważ nie znam getprocessid()funkcji w C / C ++ pod Linuksem.
Alexis Wilke

12

Valgrind może wyświetlać szczegółowe informacje, ale znacznie spowalnia aplikację docelową i przez większość czasu zmienia zachowanie aplikacji.
Exmap był czymś, czego jeszcze nie znałem, ale wydaje się, że potrzebujesz modułu jądra, aby uzyskać informacje, które mogą być przeszkodą.

Zakładam, że każdy, kto chce wiedzieć o „wykorzystaniu pamięci” WRT, jest następujący:
W systemie Linux ilość pamięci fizycznej, którą może wykorzystać pojedynczy proces, można z grubsza podzielić na następujące kategorie.

  • Ma anonimową pamięć mapowaną

    • .p prywatny
      • .d dirty == kupka malloc / mmapped i stos przydzielona i zapisana pamięć
      • .c wyczyść == malloc / mmapped pamięć sterty i stosu raz przydzielona, ​​zapisana, a następnie zwolniona, ale jeszcze nie odzyskana
    • .s udostępnione
      • .d dirty == kupka malloc / mmaped może zostać skopiowana do zapisu i udostępniona między procesami (edytowana)
      • .c clean == kupka malloc / mmaped może zostać skopiowana przy zapisie i udostępniona między procesami (edytowana)
  • Mn nazwana pamięć mapowana

    • .p prywatny
      • .d dirty == plik zmapowana pamięć zapisana prywatna
      • .c clean == zmapowany tekst programu / biblioteki zmapowany prywatnie
    • .s udostępnione
      • .d brudny == współdzielona pamięć zapisana w pliku mapowana na mm
      • .c clean == mapowany tekst biblioteki udostępniony mapowany

Narzędzie zawarte w systemie Android o nazwie showmap jest dość przydatne

virtual                    shared   shared   private  private
size     RSS      PSS      clean    dirty    clean    dirty    object
-------- -------- -------- -------- -------- -------- -------- ------------------------------
       4        0        0        0        0        0        0 0:00 0                  [vsyscall]
       4        4        0        4        0        0        0                         [vdso]
      88       28       28        0        0        4       24                         [stack]
      12       12       12        0        0        0       12 7909                    /lib/ld-2.11.1.so
      12        4        4        0        0        0        4 89529                   /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
      28        0        0        0        0        0        0 86661                   /usr/lib/gconv/gconv-modules.cache
       4        0        0        0        0        0        0 87660                   /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
       4        0        0        0        0        0        0 89528                   /usr/lib/locale/en_US.utf8/LC_TELEPHONE
       4        0        0        0        0        0        0 89527                   /usr/lib/locale/en_US.utf8/LC_ADDRESS
       4        0        0        0        0        0        0 87717                   /usr/lib/locale/en_US.utf8/LC_NAME
       4        0        0        0        0        0        0 87873                   /usr/lib/locale/en_US.utf8/LC_PAPER
       4        0        0        0        0        0        0 13879                   /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
       4        0        0        0        0        0        0 89526                   /usr/lib/locale/en_US.utf8/LC_MONETARY
       4        0        0        0        0        0        0 89525                   /usr/lib/locale/en_US.utf8/LC_TIME
       4        0        0        0        0        0        0 11378                   /usr/lib/locale/en_US.utf8/LC_NUMERIC
    1156        8        8        0        0        4        4 11372                   /usr/lib/locale/en_US.utf8/LC_COLLATE
     252        0        0        0        0        0        0 11321                   /usr/lib/locale/en_US.utf8/LC_CTYPE
     128       52        1       52        0        0        0 7909                    /lib/ld-2.11.1.so
    2316       32       11       24        0        0        8 7986                    /lib/libncurses.so.5.7
    2064        8        4        4        0        0        4 7947                    /lib/libdl-2.11.1.so
    3596      472       46      440        0        4       28 7933                    /lib/libc-2.11.1.so
    2084        4        0        4        0        0        0 7995                    /lib/libnss_compat-2.11.1.so
    2152        4        0        4        0        0        0 7993                    /lib/libnsl-2.11.1.so
    2092        0        0        0        0        0        0 8009                    /lib/libnss_nis-2.11.1.so
    2100        0        0        0        0        0        0 7999                    /lib/libnss_files-2.11.1.so
    3752     2736     2736        0        0      864     1872                         [heap]
      24       24       24        0        0        0       24 [anon]
     916      616      131      584        0        0       32                         /bin/bash
-------- -------- -------- -------- -------- -------- -------- ------------------------------
   22816     4004     3005     1116        0      876     2012 TOTAL

10

Trzy kolejne metody do wypróbowania:

  1. ps aux --sort pmem
    Sortuje dane wyjściowe według %MEM.
  2. ps aux | awk '{print $2, $4, $11}' | sort -k2r | head -n 15
    Sortuje za pomocą rur.
  3. top -a
    Zaczyna się najlepsze sortowanie według %MEM

(Wyodrębniono stąd )


2
topi prawdopodobnie inni nie dają dokładnej reprezentacji pamięci faktycznie używanej przez proces. Na przykład mam 64 GB pamięci RAM i mam 10 postgresprocesów raportujących 16 GB RES i 25% MEM. Oczywiście nie wszyscy używają 25% ... Każdy z nich ma również 15GiB SHR i wygląda na to, że je dzielą.
sudo

8
#!/bin/ksh
#
# Returns total memory used by process $1 in kb.
#
# See /proc/NNNN/smaps if you want to do something
# more interesting.
#

IFS=$'\n'

for line in $(</proc/$1/smaps)
do
   [[ $line =~ ^Size:\s+(\S+) ]] && ((kb += ${.sh.match[1]}))
done

print $kb

5
ksh jest standardową powłoką. Może nie być instalowany domyślnie na dystrybucjach Linuksa dla użytkowników komputerów stacjonarnych lub w celach minimalistycznych, ale jest to tylko jedno polecenie w prawie każdym systemie operacyjnym Unix / Linux. (tj. na wszystkich BSD, na wszystkich prawdziwych systemach UNIX, na RHEL, na SLES, na Debianie, na Ubuntu, na OSX)
Florian Heigl

Ten plik jest domyślnie dostępny tylko dla użytkownika root.
Dmitry Ginzburg

Poniżej znajduje się tylko powyższe przepisane na sed | awk i działa w Busybox v1.23.2: sed -n 's/^Size:\s\+\(\S\+\) .*/\1/p' /proc/$1/smaps | awk '{s+=$1} END {print s}'
Ján Sáreník

1
@Catskul - Standard POSIX określa swoją standardową powłokę jako ścisły podzbiór powłoki Korn, ulepszonej wersji powłoki Bourne.
ceph3us

8

Używam htop; jest to bardzo dobry program konsoli podobny do Menedżera zadań Windows.


Użyłem htopi jest lepszy niż górny, ale nadal pokaże wszystkie wątki z różnych aplikacji bez grupowania ich, co czyni go prawie tak bezużytecznym jak górny.
sorin

1
$ htop -p $ (pgrep <nazwa twojego procesu> | xargs | tr '' ',')
AAAfarmclub

6

Jeśli proces nie zużywa zbyt dużo pamięci (albo dlatego, że spodziewane jest, że tak się dzieje, albo jakieś inne polecenie dało to wstępne wskazanie), a proces może wytrzymać zatrzymanie na krótki czas, możesz spróbować użyj polecenia gcore.

gcore <pid>

Sprawdź rozmiar wygenerowanego pliku podstawowego, aby uzyskać dobry pomysł na ilość pamięci używanej przez dany proces.

Nie zadziała to zbyt dobrze, jeśli proces wykorzystuje setki megabajtów lub koncertów, ponieważ tworzenie rdzenia może potrwać kilka sekund lub minut, w zależności od wydajności we / wy. Podczas tworzenia rdzenia proces zostaje zatrzymany (lub „zamrożony”), aby zapobiec zmianom pamięci. Więc uważaj.

Upewnij się również, że punkt podłączenia, w którym generowany jest rdzeń, ma dużo miejsca na dysku i że system nie zareaguje negatywnie na tworzenie pliku rdzenia w tym konkretnym katalogu.


6

Korzystam z Arch Linux i jest ten cudowny pakiet o nazwie ps_mem

ps_mem -p <pid>

Przykładowy wynik

$ ps_mem -S -p $(pgrep firefox)

Private   +   Shared  =  RAM used   Swap used   Program

355.0 MiB +  38.7 MiB = 393.7 MiB    35.9 MiB   firefox
---------------------------------------------
                        393.7 MiB    35.9 MiB
=============================================

5

Poniższa linia poleceń podaje całkowitą pamięć używaną przez różne procesy uruchomione na komputerze z systemem Linux 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}'

5

Dobrym testem wykorzystania bardziej „rzeczywistego świata” jest otwarcie aplikacji, a następnie uruchomienie vmstat -si sprawdzenie statystyki „pamięci aktywnej”. Zamknij aplikację, poczekaj kilka sekund i uruchom vmstat -sponownie. Jakkolwiek zwolniona została aktywna pamięć, widocznie była używana przez aplikację.


3
Jak byłoby to lepsze niż ps? Ma wszystkie ograniczenia ps i jest jeszcze bardziej niedokładny ...
Lester Cheung

Typowy system uniksowy ma wiele procesów rozpoczynających się i kończących przez cały czas. Nie możesz przewidzieć wolnej pamięci RAM.
Raúl Salinas-Monteagudo

4

Zdobądź valgrind. daj mu swój program do uruchomienia, a powie ci wiele o zużyciu pamięci.

Miałoby to zastosowanie tylko w przypadku programu, który działa przez pewien czas i zatrzymuje się. Nie wiem, czy valgrind może zdobyć już działający proces, czy też nie powinien zatrzymać procesów takich jak demony.


Nie, nie można „dołączyć” valgrinda do działającego procesu. To z założenia.
Dima Tisnek

3

Edycja: działa to w 100% dobrze tylko wtedy, gdy wzrasta zużycie pamięci

Jeśli chcesz monitorować wykorzystanie pamięci przez dany proces (lub grupę przetworzonych współużytkowanych wspólnych nazw, np. google-chromeMożesz użyć mojego skryptu bash:

while true; do ps aux | awk ‚{print $5, $11}’ | grep chrome | sort -n > /tmp/a.txt; sleep 1; diff /tmp/{b,a}.txt; mv /tmp/{a,b}.txt; done;

to będzie stale szukało zmian i je drukowało.

wprowadź opis zdjęcia tutaj


3

Jeśli chcesz czegoś szybszego niż profilowanie za pomocą Valgrind, a twoje jądro jest starsze i nie możesz używać smapów, ps z opcjami pokazania zestawu rezydentnego procesu (z ps -o rss,command) może dać ci szybką i rozsądną _aproximation_rzeczywistą ilość używana pamięć nie wymieniona.


3

Sugerowałbym, abyś używał na szczycie. Możesz znaleźć wszystko na ten temat na tej stronie . Jest w stanie zapewnić wszystkie niezbędne KPI dla twoich procesów, a także może przechwytywać do pliku.


2
Aby wyświetlić PSIZE ["proporcjonalny rozmiar pamięci tego procesu (lub użytkownika)] ​​uruchom na szczycie za pomocą atop -R. Aby wyświetlić podsumowanie wypychania według użytkownika p, aby posortować według zużycia pamięci, wciśnij„ M ”od góry. Daje to podobne liczby niż smem.
Markus Strauss,


1

Kolejny głos na tutaj, ale chciałbym dodać, że możesz użyć narzędzia takiego jak Alleyoop, aby pomóc w interpretacji wyników generowanych przez valgrind.

Używam tych dwóch narzędzi przez cały czas i zawsze mam szczupły, nieszczelny kod, który z dumą pokazuję;)


1

Chociaż wydaje się, że to pytanie dotyczy badania aktualnie działających procesów, chciałem zobaczyć maksymalną pamięć używaną przez aplikację od początku do końca. Oprócz valgrind, możesz używać tstime , który jest znacznie prostszy. Mierzy zużycie pamięci „highwater” (RSS i wirtualne). Z tej odpowiedzi .


Większość aplikacji - to znaczy tych, które używają malloc () i bibliotek pamięci podobnych do malloc - nie zwraca stron do systemu operacyjnego, dopóki nie zakończy się proces. Tak więc ilość, którą widzisz w PS (lub innym narzędziu, które nie zagłębia się w stos procesu) będzie oznaczeniem wysokiego poziomu.
David C.

0

Na podstawie odpowiedzi na powiązane pytanie .

Możesz użyć SNMP, aby uzyskać pamięć i użycie procesora przez proces na określonym urządzeniu w sieci :)

Wymagania:

  • na urządzeniu uruchamiającym proces powinien być zainstalowany i uruchomiony snmp
  • snmp powinien być skonfigurowany do akceptowania żądań, z których będziesz uruchamiał poniższy skrypt (może być skonfigurowany w snmpd.conf)
  • powinieneś znać identyfikator procesu (pid) procesu, który chcesz monitorować

Uwagi:

  • HOST-RESOURCES-MIB :: hrSWRunPerfCPU to liczba centów sekund całkowitego zużycia zasobów procesora przez system. Należy pamiętać, że w systemie wieloprocesorowym wartość ta może wzrosnąć o więcej niż jeden centi-sekundę w jednym centy-sekundie czasu rzeczywistego (zegar ścienny).

  • HOST-RESOURCES-MIB :: hrSWRunPerfMem to całkowita ilość rzeczywistej pamięci systemowej przydzielonej dla tego procesu.

**

Skrypt monitorowania procesu:

**

echo "IP: "
read ip
echo "specfiy pid: "
read pid
echo "interval in seconds:"
read interval

while [ 1 ]
do
    date
    snmpget -v2c -c public $ip HOST-RESOURCES-MIB::hrSWRunPerfCPU.$pid
    snmpget -v2c -c public $ip HOST-RESOURCES-MIB::hrSWRunPerfMem.$pid
    sleep $interval;
done

0

/ prox / xxx / numa_maps podaje tam trochę informacji: N0 = ??? N1 = ???. Ale ten wynik może być niższy niż rzeczywisty, ponieważ uwzględnia tylko te, które zostały dotknięte.


-1

Użyj wbudowanego narzędzia GUI do monitorowania systemu dostępnego w Ubuntu


1
Przynajmniej od 16.04 to działa bardzo dobrze. Jest bardzo podobny do góry, używana pamięć nie jest bardzo precyzyjna ...
Alexis Wilke
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.