Leggere "free: 180MB" su un server da 8 GB fa spaventare qualcuno ogni giorno, e quasi sempre va tutto bene. Linux usa la memoria avanzata come cache del disco e la restituisce nell'istante in cui qualcosa la richiede. Il numero da leggere è available, non free.

free -h
#               total   used   free   shared  buff/cache   available
# Mem:           7.8Gi  2.1Gi  180Mi   120Mi      5.5Gi       5.3Gi

5,3 Gi in available vuol dire che ci sono 5,3 Gi da prendere. La cache non è memoria persa; è memoria che fa qualcosa di utile finché non serve.

Lo swap è il numero che conta

Che lo swap sia OCCUPATO non è il problema. Che ci si stia attivamente scrivendo e leggendo sì: la macchina sposta pagine sul disco per far spazio, e il disco è migliaia di volte più lento della memoria. Tutto è lento e nell'applicazione non c'è nulla che lo spieghi.
vmstat 2 5
# watch the si and so columns - sustained non-zero is thrashing

Trovi che cosa la tiene

ps aux --sort=-%mem | head -10
smem -rs uss 2>/dev/null | head -10

uss è la memoria che un processo libererebbe davvero se terminasse, ed è la cifra onesta. rss conta due volte le librerie condivise e fa sembrare enorme ogni worker PHP.

La risposta di sempre

  • Troppi worker PHP. Un pm.max_children preso da una guida invece che calcolato dalla sua RAM. Divida la memoria disponibile per il worker medio, e stia largo.
  • Un innodb_buffer_pool_size troppo grande. Un database a cui si chiede di tenere in cache più di quanto la macchina possieda.
  • Una perdita in un worker di lunga durata. Lo riavvii periodicamente; php-fpm lo fa con pm.max_requests.
Un po' di swap è sano: consente al kernel di spostare da parte le pagine davvero inattive. Un server con lo swap disattivato del tutto non ha cuscinetto e viene ucciso di netto appena la memoria scarseggia.