====== Monitorizarea memoriei pe Linux ======
Diagnosticarea problemelor de memorie pe Linux poate fi frustrantă dacă nu știi ce unelte să folosești și ce înseamnă cifrele pe care le vezi. Același sistem poate părea că are memorie liberă din belșug sau că e la limită, în funcție de cum interpretezi datele. Acest articol acoperă toate uneltele importante pentru monitorizarea memoriei, de la comenzile de bază pe care le folosești zilnic până la analiza detaliată per proces.
===== free =====
''free'' este prima comandă la care ajungi când vrei o imagine rapidă a memoriei. Rulezi întotdeauna cu ''-h'' pentru valori lizibile:
free -h
total used free shared buff/cache available
Mem: 15Gi 4.2Gi 6.1Gi 412Mi 5.1Gi 10Gi
Swap: 2.0Gi 128Mi 1.9Gi
Coloana care contează cu adevărat este **available** - nu **free**. Iată de ce:
**free** arată memoria complet neutilizată, fără niciun conținut. Pare mic pentru că Linux folosește RAM-ul liber ca cache de disc - un comportament normal și de dorit.
**buff/cache** este memoria folosită de kernel pentru buffere I/O și cache de pagini. Această memorie poate fi eliberată imediat dacă un proces are nevoie - kernelul o sacrifică fără probleme.
**available** este suma dintre **free** și partea din **buff/cache** care poate fi eliberată imediat. Aceasta este memoria reală disponibilă pentru procese noi fără a folosi swap. Dacă **available** se apropie de zero, sistemul e sub presiune reală de memorie.
**shared** este memoria partajată între procese, inclusiv tmpfs (''/dev/shm'', ''/run'').
Urmărești evoluția în timp cu:
watch -n 2 free -h
===== /proc/meminfo =====
''/proc/meminfo'' este sursa de date pentru toate celelalte unelte - ''free'', ''htop'' și altele citesc de aici. Conține zeci de câmpuri, dar cele mai relevante sunt:
cat /proc/meminfo
MemTotal: 16248832 kB # RAM fizic total
MemFree: 6291456 kB # RAM complet liber
MemAvailable: 10485760 kB # RAM disponibil pentru procese noi
Buffers: 524288 kB # Buffer cache pentru metadata de disc
Cached: 4718592 kB # Page cache (conținut fișiere)
SwapCached: 32768 kB # Pagini aduse din swap, încă în swap
Active: 5242880 kB # Pagini accesate recent
Inactive: 3145728 kB # Pagini candidate pentru swap/eliberare
Active(anon): 2097152 kB # Pagini anonime active (heap, stack)
Inactive(anon): 1048576 kB # Pagini anonime inactive
Active(file): 3145728 kB # Cache de fișiere accesate recent
Inactive(file): 2097152 kB # Cache de fișiere accesate mai demult
SwapTotal: 2097152 kB # Swap total
SwapFree: 1966080 kB # Swap disponibil
Dirty: 16384 kB # Pagini modificate, neîncă scrise pe disc
Writeback: 0 kB # Pagini în curs de scriere pe disc
AnonPages: 3145728 kB # Total pagini anonime mapate
Mapped: 524288 kB # Fișiere mapate în memorie (mmap)
Shmem: 425984 kB # Memorie partajată și tmpfs
Slab: 786432 kB # Cache-uri interne ale kernelului
SReclaimable: 524288 kB # Slab care poate fi eliberat
SUnreclaim: 262144 kB # Slab care nu poate fi eliberat
HugePages_Total: 0 # Huge Pages rezervate
HugePages_Free: 0 # Huge Pages disponibile
AnonHugePages: 614400 kB # Memorie anonimă în THP
Câteva valori care merită atenție specială:
**Dirty** - pagini modificate în memorie care nu au fost încă scrise pe disc. O valoare constant mare poate indica un sistem care scrie mult pe disc și e limitat de I/O.
**Slab** - memoria folosită de kernelul însuși pentru structuri interne (inode cache, dentry cache, etc.). Pe serverele de fișiere sau cu multe procese, Slab poate ajunge la sute de MB sau chiar GB. **SReclaimable** e partea care poate fi eliberată sub presiune.
**SwapCached** - pagini care au fost aduse din swap înapoi în RAM, dar care există și în swap. Dacă procesul le accesează din nou, nu mai trebuie citite de pe disc. O valoare pozitivă indică faptul că sistemul a swap-at recent.
===== vmstat =====
''vmstat'' oferă o vedere de ansamblu a sistemului: memorie, swap, I/O, procesor - totul într-o singură linie. Este ideal pentru monitorizarea în timp real a presiunii pe memorie:
vmstat 2 10
Afișează 10 linii la interval de 2 secunde. Prima linie conține medii de la pornire și se ignoră de obicei.
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 131072 6291456 524288 4718592 0 0 12 48 245 512 5 2 92 1 0
0 0 131072 6287360 524288 4722688 0 0 0 16 198 423 2 1 97 0 0
Coloanele critice pentru memorie și swap:
**swpd** - cantitatea totală de swap folosit în KB. Dacă crește constant, sistemul e sub presiune.
**free** - RAM liber în KB (nu include buff/cache).
**si** (swap in) - pagini aduse din swap în RAM pe secundă. Valori constant diferite de zero indică un sistem care lucrează cu date paginate.
**so** (swap out) - pagini trimise din RAM în swap pe secundă. Dacă **so** e constant pozitiv, kernelul paginează activ și performanța suferă.
**bi/bo** - blocuri citite/scrise pe disc pe secundă. Valori mari corelate cu **si/so** confirmă că swap-ul pe disc e activ.
Pentru o sesiune de monitorizare mai lungă, redirecționezi output-ul:
vmstat 5 > /tmp/vmstat_log.txt &
===== htop =====
''htop'' este monitorul interactiv cel mai folosit pe Linux și afișează informații despre memorie atât la nivel de sistem cât și per proces. Barele din partea de sus arată RAM-ul și swap-ul, cu coduri de culoare:
* **Verde** - memorie folosită de procese
* **Albastru** - buffer cache
* **Galben/Portocaliu** - cache de pagini
* **Roșu** - swap folosit
Coloanele relevante pentru memorie în lista de procese sunt **RES** (memoria fizică reală folosită de proces, fără pagini partajate) și **VIRT** (spațiul virtual total alocat, irelevant pentru consumul real).
Poți filtra după consum de memorie apăsând ''F6'' și selectând ''MEM%''. Pentru a vedea swap-ul per proces, adaugi coloana ''SWAP'' prin ''F2 → Columns''.
===== ps =====
''ps'' este util pentru snapshots rapide ale consumului de memorie per proces. Afișezi procesele sortate după consum de RAM:
ps aux --sort=-%mem | head -20
sau cu mai multe detalii:
ps -eo pid,ppid,cmd,%mem,%cpu,rss,vsz --sort=-%mem | head -20
**RSS** în output-ul ''ps'' este în KB și reprezintă memoria fizică ocupată, incluzând paginile partajate - poate supraestima consumul real dacă procesul folosește multe biblioteci partajate.
===== smem =====
''smem'' este unealta cea mai precisă pentru analiza consumului de memorie per proces, deoarece calculează **PSS** (Proportional Set Size) - memoria partajată este împărțită proporțional între procesele care o folosesc, oferind o imagine realistă a consumului real.
Instalezi:
# Ubuntu/Debian
apt install smem
# Fedora
dnf install smem
# Arch Linux
pacman -S smem
Afișezi procesele sortate după PSS:
smem -rs pss | head -20
Afișezi consumul total per utilizator:
smem -u
Afișezi consumul per program (agregate toate instanțele):
smem -P nginx -r
Un raport complet cu toate metricile:
smem -r -k
''-k'' afișează valorile în KB/MB/GB în loc de bytes brute.
===== pmap =====
''pmap'' arată harta de memorie detaliată a unui singur proces - fiecare zonă de memorie mapată, cu dimensiunea și permisiunile ei:
pmap -x PID
Address Kbytes RSS Dirty Mode Mapping
0000563f2a000000 2048 1024 0 r-x-- nginx
0000563f2a200000 256 256 256 r---- nginx
0000563f2a240000 64 64 64 rw--- nginx
00007f8b4c000000 51200 32768 32768 rw--- [ anon ]
00007f8b4f000000 131072 0 0 ----- [ anon ]
...
Coloanele importante sunt **RSS** (memoria fizică efectiv ocupată) și **Dirty** (pagini modificate față de versiunea de pe disc). Zonele marcate ''anon'' sunt heap sau memorie anonimă (malloc), cele cu nume de fișiere sunt biblioteci sau fișiere mapate.
Pentru un sumar rapid:
pmap -x PID | tail -1
Ultima linie conține totalurile. Util pentru a verifica rapid cât ocupă un proces fără a parcurge toată lista.
===== /proc/PID/smaps =====
''/proc/PID/smaps'' conține informațiile cele mai detaliate despre memoria unui proces, câmpuri pentru fiecare zonă mapată. Este sursa de date pentru ''smem'' și ''pmap''. Pentru un sumar rapid al câmpurilor agregate:
cat /proc/PID/smaps_rollup
Rss: 45678 kB
Pss: 12345 kB
Pss_Anon: 8192 kB
Pss_File: 4096 kB
Pss_Shmem: 57 kB
Shared_Clean: 32768 kB
Shared_Dirty: 0 kB
Private_Clean: 1024 kB
Private_Dirty: 7168 kB
Referenced: 45678 kB
Anonymous: 8192 kB
AnonHugePages: 4096 kB
Swap: 2048 kB
SwapPss: 1024 kB
**Swap** arată exact câtă memorie a acestui proces e în swap în momentul citirii. **SwapPss** e varianta proporțională pentru paginile de swap partajate.
Pentru a vedea toate procesele cu swap, sortate:
for pid in /proc/[0-9]*/smaps_rollup; do
p=$(dirname $pid | xargs basename)
swap=$(awk '/^Swap:/{print $2}' $pid 2>/dev/null)
name=$(cat /proc/$p/comm 2>/dev/null)
echo "$swap $p $name"
done | sort -rn | awk '$1>0' | head -20
===== slabtop =====
Cache-ul Slab al kernelului poate consuma cantități semnificative de RAM pe servere active, fără să apară în statisticile per proces. ''slabtop'' este htop-ul pentru cache-urile interne ale kernelului:
slabtop
Sau un snapshot non-interactiv:
slabtop -o | head -30
Cache-urile frecvent mari:
* **dentry** - cache pentru intrările de director, crește pe sisteme cu multe fișiere
* **inode_cache** - cache pentru inoduri de fișiere
* **ext4_inode_cache** sau similar - specific sistemului de fișiere
* **kmalloc-*** - alocări generale ale kernelului
Pe un server cu NFS sau cu multe fișiere deschise simultan, dentry și inode cache pot ajunge la câțiva GB. Sunt eliberate automat sub presiune de memorie (fac parte din SReclaimable).
Poți elibera manual cache-urile Slab (util pentru testare, nu pentru producție):
echo 2 > /proc/sys/vm/drop_caches # eliberează dentry și inode cache
echo 3 > /proc/sys/vm/drop_caches # eliberează page cache, dentry și inode
Pe producție, această comandă poate degrada temporar performanța - kernelul va trebui să reconstruiască cache-urile din disc.
===== sar =====
''sar'' (System Activity Reporter) face parte din pachetul ''sysstat'' și colectează statistici de sistem la intervale regulate, stocându-le pentru analiză ulterioară. Ideal pentru a înțelege ce s-a întâmplat cu memoria ieri noapte sau săptămâna trecută.
Instalezi și activezi colectarea:
# Ubuntu/Debian
apt install sysstat
systemctl enable --now sysstat
# Fedora
dnf install sysstat
systemctl enable --now sysstat
Raport de memorie pentru ziua curentă:
sar -r
Raport pentru o zi specifică (datele sunt salvate în ''/var/log/sa/''):
sar -r -f /var/log/sa/sa17 # ziua 17 a lunii curente
Urmărești swap-ul în timp:
sar -W
Coloanele **pswpin/s** și **pswpout/s** arată paginile swap-ate per secundă - echivalentul **si/so** din vmstat, dar cu istoric.
===== Scenarii practice de diagnosticare =====
==== Sistemul e lent - e vina memoriei? ====
# Verifici rapid disponibilul
free -h
# Confirmi cu vmstat - cauți si/so diferite de zero
vmstat 2 5
# Identifici procesele mari
ps aux --sort=-%mem | head -10
Dacă **available** e sub 500MB și **so** e constant pozitiv, confirmi problema de memorie. Dacă **available** e rezonabil și **so** e zero, problema e probabil altundeva (CPU, I/O, rețea).
==== Un serviciu consumă prea mult RAM ====
# Găsești PID-ul
pgrep -f nume_serviciu
# Verifici consumul real (PSS)
cat /proc/PID/smaps_rollup | grep Pss
# Sau cu smem
smem -P nume_serviciu -r
==== Swap-ul a crescut brusc ====
# Găsești ce e în swap
for pid in /proc/[0-9]*/smaps_rollup; do
p=$(dirname $pid | xargs basename)
swap=$(awk '/^Swap:/{print $2}' $pid 2>/dev/null)
name=$(cat /proc/$p/comm 2>/dev/null)
echo "$swap $p $name"
done | sort -rn | awk '$1>0' | head -10
# Verifici când s-a întâmplat
journalctl -k | grep -i "oom\|memory"
==== Slab consumă mult ====
# Verifici totalul
grep Slab /proc/meminfo
# Identifici cache-urile mari
slabtop -o | head -20
===== Resurse suplimentare =====
* [[memorie_virtuala|Cum funcționează memoria virtuală pe Linux]] - conceptele de bază
* [[swap|Swap pe Linux]] - gestionarea memoriei virtuale pe disc
* [[zram_si_zswap|zram și zswap]] - alternative moderne la swap-ul clasic
* [[oom_killer|OOM Killer]] - ce se întâmplă când memoria se epuizează
* [[huge_pages|Huge Pages]] - optimizarea performanței pentru aplicații mari
{{tag>linux memorie monitorizare kernel swap htop vmstat diagnosticare}}