Perché il tuo server usa swap con RAM libera (e come scoprire chi è il colpevole con smem)
Capita spesso: un server ha 32 o 64 GB di RAM, il carico è tutto sommato modesto, eppure free -h mostra qualche centinaio di MB o addirittura qualche GB in swap. Il riflesso istintivo di molti sistemisti è colpevolizzare la RAM insufficiente e chiedere un upgrade. Nella maggior parte dei casi, però, il problema non è la quantità di memoria disponibile, ma quali processi stanno finendo in swap e perché. Per rispondere serve uno strumento che guardi dentro ai singoli processi, non solo ai numeri aggregati: smem.
Perché Linux usa lo swap anche con RAM libera
Il kernel Linux non tratta la RAM come una risorsa da tenere il più vuota possibile: la usa aggressivamente per la page cache, per velocizzare I/O su file e librerie. Quando il kernel individua pagine di memoria che non vengono acquisite/toccate da tempo, può decidere di spostarle in swap per liberare RAM fisica da destinare alla cache, anche se tecnicamente c’è ancora memoria “libera” disponibile. Questo comportamento è regolato dal parametro vm.swappiness (0-100, con default storicamente a 60 su molte distribuzioni), che indica al kernel quanto è propenso a scambiare memoria anonima verso lo swap piuttosto che liberare pagine di cache.
Il punto chiave: prima di toccare vm.swappiness alla cieca, bisogna sapere chi sta effettivamente occupando swap. Un valore aggregato come quello di free non lo dice. Serve la vista per processo.
smem: memoria proporzionale, non solo RSS
Tool classici come top o ps mostrano RSS (Resident Set Size), che però ha un difetto noto: se due processi condividono le stesse pagine di memoria (librerie condivise, memoria mappata), quella memoria viene contata per intero in ognuno dei due, gonfiando artificialmente i numeri quando si sommano i processi.
smem risolve il problema calcolando anche:
- USS (Unique Set Size): memoria usata esclusivamente da quel processo, non condivisa con nessun altro — utile per capire quanto libereresti davvero uccidendo il processo
- PSS (Proportional Set Size): memoria condivisa divisa proporzionalmente tra i processi che la usano — la metrica più corretta per sommare l’uso reale di memoria di un sistema senza doppi conteggi
- Swap: quanta memoria di quello specifico processo è stata spostata su disco
Installazione
smem non è quasi mai preinstallato, ma è nei repository di tutte le principali distribuzioni:
# RHEL / CentOS / AlmaLinux / Fedora
dnf install smem
# Debian / Ubuntu
apt install smem
Uso pratico: trovare chi consuma swap
Il comando base per ordinare i processi per swap consumato:
smem -rs swap
Output tipico (troncato):
PID User Command Swap USS PSS RSS
28986 mysql /usr/sbin/mysqld --daemon 476372 10963864 10963932 10965112
29152 root /usr/sbin/rsyslogd -n 371424 3956 17475 43352
31423 root /opt/fluent-bit/bin/fluent 22508 26612 26739 29100
Da un output così è immediato capire che mysqld e rsyslogd sono i principali responsabili dell’uso di swap su questo host, e non un generico “poca RAM”. Da qui l’indagine si sposta su quel servizio specifico: per MySQL, ad esempio, tipicamente significa rivedere innodb_buffer_pool_size rispetto alla RAM totale disponibile, o verificare connessioni/thread che allocano memoria inutilmente.
Alcune varianti utili del comando:
# Ordina per USS (memoria realmente esclusiva del processo)
smem -rs uss
# Filtra per utente
smem -u
# Vista grafica a torta per RSS (richiede matplotlib)
smem --pie name -s rss
Dalla diagnosi al tuning
Una volta identificati i servizi che finiscono in swap, ci sono due strade complementari:
- Agire sul servizio: ridimensionare i buffer/pool applicativi (buffer pool di MySQL, heap JVM, cache applicative) in base alla RAM effettivamente disponibile, invece di lasciare valori di default pensati per macchine generiche.
- Agire sul kernel, solo dopo aver capito il quadro reale: ridurre
vm.swappinessper rendere il kernel meno aggressivo nello spostare memoria anonima in swap:
sysctl vm.swappiness=1
echo 'vm.swappiness=1' >> /etc/sysctl.conf
Da notare che vm.swappiness=0 non disabilita completamente lo swap su kernel recenti (dal 3.5 in poi il comportamento è cambiato rispetto alle versioni più vecchie), mentre valori molto bassi come 1 riducono drasticamente la propensione allo swap mantenendo comunque una valvola di sicurezza in caso di pressione di memoria reale. Su un database server dedicato, dove si preferisce quasi sempre tenere i dati “caldi” in RAM piuttosto che liberare cache, è una delle prime ottimizzazioni da considerare.
Conclusione
Vedere swap attivo su un server con RAM apparentemente libera non è di per sé un allarme: è il comportamento normale di un kernel che ottimizza l’uso della cache. Il problema comincia quando lo swap coinvolge processi critici per la latenza, come un database o un servizio applicativo, degradando le performance in modo silenzioso. smem -rs swap è il primo comando da lanciare in questi casi: in pochi secondi isola il processo responsabile, distingue la memoria condivisa da quella esclusiva, e trasforma un sintomo generico (“il server è lento”) in un’azione concreta di tuning, sul servizio o sul kernel.
Fonte: LinuxBlog.io, “Diagnosing Swap Usage with smem on Linux”.