4. Процессы, CPU, память
PID/PPID, load average, OOM Killer, память (RSS/VSZ/page cache/swap), nice/renice и основы cgroups — для диагностики тормозов и падений в production.
PID и PPID
PID (Process ID) — уникальный идентификатор процесса в системе. PPID (Parent Process ID) — PID родительского процесса. Дерево процессов строится по этим связям; init/systemd (PID 1) — корень. Команды: ps -ef, ps -o pid,ppid,cmd, pstree. При «зомби» или зависших дочерних процессах смотрят родителя (PPID) и перезапускают сервис или корректно завершают потомков.
Context switching
Переключение контекста (context switch) — когда ядро забирает CPU у одного процесса и отдаёт другому: сохраняется контекст (регистры, состояние) первого, подгружается контекст второго. Частые переключения создают накладные расходы (кэш, TLB). Высокий показатель context switch при нормальном CPU может означать много потоков/процессов, конкурирующих за CPU, или активный I/O (процессы часто блокируются и просыпаются). Смотреть: vmstat 1, pidstat -w, в /proc: контекстные переключения по системе и по процессам.
Load average
Load average — три числа (за 1, 5 и 15 минут), показывающие среднее число процессов в состоянии готовы к выполнению (runnable) или ожидания I/O (uninterruptible sleep, D). Не «процент CPU», а «сколько процессов в среднем ждали CPU или диск». Интерпретация:
- На одноядерной системе load 1.0 — в среднем один процесс ждал; load 4.0 — в среднем четыре.
- На 4 ядрах load 4.0 может быть нормой (все ядра заняты), а load 16 — сильная перегрузка (много ожидающих).
Высокий load при низком CPU часто говорит о I/O wait: процессы ждут диск или сеть (состояние D), CPU простаивает. Смотреть: top (wa — iowait), iostat, vmstat (блоки в io). Высокий load при высоком CPU — много вычислений, процессы конкурируют за процессор; смотреть, какие процессы: top, pidstat, perf.
OOM Killer
Когда ядру не хватает памяти (включая учёт буферов и возможности вытеснения в swap), оно вызывает OOM Killer и завершает один или несколько процессов, чтобы освободить память. В логах (dmesg, journalctl) появляются сообщения вида «Out of memory: Killed process …». Выбор жертвы основан на oom_score и oom_score_adj; можно понижать приоритет для важных процессов (меньше шанс быть убитым). После OOM в логах видно PID и имя процесса; дальше — разбирать, почему память закончилась (утечка, неверные лимиты, нехватка ресурса на машине).
Память: RSS, VSZ, page cache, swap
RSS и VSZ
- RSS (Resident Set Size) — объём физической памяти (RAM), занятой процессом (его страницами). То, что реально давит на RAM.
- VSZ (Virtual Size) — размер виртуального адресного пространства процесса (включая отображённые файлы, разделяемые библиотеки, ещё не загруженные страницы). Обычно больше RSS.
В top, ps смотрят RSS для оценки «кто сколько ест» памяти. Сортировка по памяти: в top — M, в ps — ps -eo pid,rss,vsz,cmd --sort=-rss.
Page cache и swap
- Page cache — кэш страниц файлов в RAM. Свободная память ядро использует под кэш; при нехватке памяти кэш вытесняется. В
freeвидно «cached»; «available» — оценка памяти, доступной для приложений (с учётом возможности освободить кэш). - Swap — вынос страниц на диск (swap-раздел или файл). При активном swap диски активно пишут/читают, система может «тормозить». Мониторить:
free,vmstat,swapon -s.
Nice, renice и cgroups (база)
Nice и renice
Nice — значение приоритета планировщика для процесса (-20 … 19). Чем выше nice (например, 19), тем ниже приоритет — процесс получает меньше CPU при конкуренции. Запуск с пониженным приоритетом: nice -n 19 heavy_task. Изменить у уже работающего: renice -n 19 -p <PID>. Обычные пользователи могут только повышать nice (ухудшать приоритет); понижать (улучшать) может root.
cgroups (control groups)
cgroups — механизм ядра для ограничения, учёта и приоритизации ресурсов (CPU, память, I/O) группой процессов. systemd, Docker, Kubernetes используют cgroups для лимитов. Версия интерфейса — cgroups v2 (единая иерархия в /sys/fs/cgroup/). Ограничение CPU и памяти для сервиса задаётся в unit-файле (CPUQuota, MemoryMax) или через директории cgroup вручную. Понимание нужно для настройки лимитов контейнеров и сервисов и для диагностики (кто упирается в лимит).
Практика
Найти процесс, который съедает память
# Сортировка по RSS (top — нажать M для сортировки по памяти)
ps -eo pid,rss,vsz,cmd --sort=-rss | head -20
# Или через top
top -o %MEM
# Детали по процессу (smaps — разбивка памяти)
cat /proc/<PID>/status | grep -i mem
По PID смотреть логи и конфигурацию приложения; при утечке — перезапуск или обновление.
Понять разницу между high load и high CPU
- High load, high CPU — много процессов активно считают. Смотреть
top,pidstat 1— какие процессы занимают CPU; оптимизация кода, масштабирование, лимиты. - High load, low CPU — процессы в основном ждут I/O (диск, сеть). Смотреть
iostat -x 1,vmstat 1(wa, блоки io), возможно диск или сеть — узкое место. Увеличить ресурс I/O или уменьшить нагрузку на диск/сеть.
Ограничить CPU и память через cgroups
В systemd для сервиса в unit-файле (или в override):
[Service]
CPUQuota=50% # не более 50% одного ядра (или 0.5 ядра при 100%)
MemoryMax=512M # жёсткий лимит памяти
MemoryHigh=400M # мягкий лимит (давление, но не kill)
Перезагрузка конфига и сервиса:
sudo systemctl daemon-reload
sudo systemctl restart myservice
Проверка: systemctl show myservice -p MemoryCurrent,MemoryMax; для процесса — в какую cgroup попал: cat /proc/<PID>/cgroup.
!!! tip "Практика"
При инциденте «всё тормозит» или «процесс убит»: 1) load average и %CPU/%wa в top; 2) free и swap; 3) топ процессов по RSS и по CPU; 4) dmesg/journal на OOM; 5) при необходимости лимиты cgroups и их достижение.
Паттерны и антипаттерны
| Паттерн | Описание |
|---|---|
| Смотреть load и CPU вместе | Высокий load при низком CPU — I/O; при высоком CPU — вычисления. |
| Лимиты памяти для сервисов | MemoryMax в systemd или аналог в оркестраторе, чтобы один процесс не съел всю машину. |
| После OOM — логи и тренд памяти | Понять, утечка или пиковая нагрузка; добавить лимиты или ресурс. |
| Антипаттерн | Почему плохо | Что делать |
|---|---|---|
| Игнорировать swap при тормозах | Активный swap даёт задержки на I/O. | Увеличить RAM или снизить потребление; swap как страховка, не как основной объём. |
| Ставить только CPU limit без памяти | OOM может убить важный процесс. | Задавать и MemoryMax (или аналог) для предсказуемого поведения. |