When the site slows, run the same triage: load against cores, the top consumers, then memory per service. Here burn.php had been spinning for 30 seconds:
nproc; top -b -n 1 -w 95 | head -3
ps -eo pid,user,%cpu,rss,etime,args --sort=-%cpu | head -3
for p in apache2 php-fpm8.5 mysqld; do
ps -C $p -o rss= | awk -v p=$p '{s+=$1; n++}
END {printf "%-10s %d procs, avg %.1f MiB, total %.1f MiB\n", p, n, s/n/1024, s/1024}'
done36
top - 14:03:59 up 1:11, 1 user, load average: 0.41, 0.20, 0.21
Tasks: 47 total, 2 running, 45 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.1 us, 0.0 sy, 0.0 ni, 96.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER %CPU RSS ELAPSED COMMAND
16000 dev 99.9 37028 00:30 php /tmp/ch01-08/burn.php
377 mysql 0.9 486236 27:25 /usr/sbin/mysqld
apache2 6 procs, avg 22.0 MiB, total 131.9 MiB
php-fpm8.5 3 procs, avg 23.1 MiB, total 69.3 MiB
mysqld 1 procs, avg 474.8 MiB, total 474.8 MiBThe load average counts processes running or waiting (R or D), to compare with nproc, but it decays slowly: 30 seconds of one pegged core read 0.41, and one core of 36 is 3.1% us. Trust the process list. A PHP worker stuck at 100% is usually an infinite loop; FPM's request_terminate_timeout caps it (PHP). RAM for PHP divided by the average worker gives pm.max_children, but RSS double-counts shared pages: Pss: in /proc/<PID>/smaps_rollup splits them (an idle FPM worker: 15,396 KiB RSS, 3,651 KiB PSS). For a process that vanished, check journalctl -k | grep -i "out of memory" (journalctl).