Finding Resource Hogs

Finding What Is Eating CPU or Memory on a Web Server

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:

A two-minute triageShell
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}'
done
Output
36
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 MiB

The 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).