Почему интервальные метрики честнее моментальных
Давай сразу про главное заблуждение. Команда ps показывает накопленные значения с момента старта процесса. Если база данных работает три недели и за это время сожрала 400 часов CPU - тебе это число ни о чём не говорит про сейчас. Может, она спит. Может, наоборот, душит сервер. ps этого не покажет, потому что усредняет по всей жизни процесса. То же с колонкой %CPU в ps: для большинства реализаций это среднее за всё время жизни процесса (отношение потраченного CPU-времени к возрасту процесса), а не "сейчас".
Представь спидометр и одометр. Одометр (ps) говорит "проехал 200 тысяч км". Спидометр (pidstat 1) говорит "едешь 90 км/ч прямо сейчас". Когда машина тормозит и ты ищешь, кто гонит, тебе нужен спидометр. Интервальная метрика - это разница между двумя снимками счётчиков из /proc, делённая на длину интервала. pidstat читает /proc/[pid]/stat, /proc/[pid]/io, /proc/[pid]/status, делает первый снимок, ждёт интервал, делает второй и печатает скорость. Поэтому первая строка вывода без интервала - это среднее с момента загрузки, а вот строки при pidstat 1 - честная скорость потребления здесь и сейчас.
Именно поэтому в перфоманс-расследованиях интервальные счётчики честнее. Ты задаёшь интервал (например, 1 секунда), и инструмент печатает свежую строку каждую секунду. Виновник всплывает сам.

Откуда берётся pidstat linux и базовый запуск
pidstat входит в пакет sysstat - тот самый набор, где живут iostat, mpstat, vmstat и sar. На голой системе его часто нет, ставится так:
Код: Выделить всё
# Debian/Ubuntu/Astra Linux
sudo apt install sysstat
# RHEL/Fedora/RED OS
sudo dnf install sysstat
Код: Выделить всё
$ pidstat -V
sysstat version 12.7.7
Код: Выделить всё
$ pidstat 1 5
Linux 6.8.0-40-generic (web-01) 06/15/2026 _x86_64_ (8 CPU)
10:21:03 UID PID %usr %system %guest %wait %CPU CPU Command
10:21:04 0 1187 2.00 1.00 0.00 0.00 3.00 2 rsyslogd
10:21:04 1000 20431 85.00 12.00 0.00 5.00 97.00 4 ffmpeg
- %usr - сколько CPU процесс тратит в пользовательском коде (твоя программа считает).
- %system - сколько в ядре (системные вызовы, работа с диском и сетью через ядро). Если тут много - процесс долбит ядро сисколлами; стоит глянуть strace или, что в 2026 правильнее по накладным расходам, eBPF-трейсинг.
- %guest - время внутри виртуальной машины (актуально, когда сам процесс - гипервизор/qemu; на обычном сервере обычно 0).
- %wait - процесс был готов считать, но ждал очереди на ядро (runqueue). Это не "ждёт диск", а "ждёт процессор". Стабильно ненулевой %wait - признак того, что готовых к счёту задач больше, чем ядер. Это насыщение CPU, а не медленный процесс.
- %CPU - суммарная загрузка процесса = %usr + %system. Важно: на 8-ядерной машине многопоточный процесс может показать до 800% (по 100% на ядро). Если хочешь, чтобы pidstat нормировал на число ядер (то есть 100% = вся машина), запускай pidstat -u --human или добавляй -I - тогда значение делится на количество CPU.
- CPU - номер ядра, на котором процесс крутился последним. Если он постоянно скачет - возможна проблема с привязкой к ядрам (CPU affinity) и потерей кэша.
sysstat в деле: ищем виновника по конкретному ресурсу
CPU - только начало. Сила pidstat в том, что им можно резать нагрузку по типу ресурса. Это четыре флага, которые стоит зазубрить.
Дисковый ввод-вывод: кто реально пишет и читает (-d)
Код: Выделить всё
$ sudo pidstat -d 1
10:31:12 UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
10:31:13 1000 8842 0.00 61440.00 0.00 14 postgres
10:31:13 999 9001 2048.00 0.00 0.00 2 clickhouse
Память и страничные ошибки (-r)
Код: Выделить всё
$ pidstat -r 1
10:35:40 UID PID minflt/s majflt/s VSZ RSS %MEM Command
10:35:41 1000 20431 320.00 45.00 2451200 812044 9.80 java
Контекстные переключения (-w)
Код: Выделить всё
$ pidstat -w 1
10:40:02 UID PID cswch/s nvcswch/s Command
10:40:03 1000 8842 150.00 3.00 postgres
10:40:03 1000 31002 5.00 9500.00 busy-loop
Потоки и конкретный PID
Флаг -t разворачивает процесс на потоки (TID), -p сужает до одного PID (или -p ALL - все задачи, включая спящие):
Код: Выделить всё
$ pidstat -t -p 20431 1
$ pidstat -d -p 8842 1
Полезные фильтры (актуально на 2026)
- -C "имя" - оставить только процессы, чьё имя команды совпадает с регуляркой: pidstat -C "postgres|nginx" 1.
- -G "имя" - то же, но матчит по полному имени процесса.
- -l - печатать полную командную строку с аргументами (отличить десяток одноимённых воркеров).
- --human - человекочитаемые размеры (1.2M вместо 1258291).
- -e program args - запустить программу и сразу мерить именно её; требует ненулевого интервала: pidstat -e -r 1 ./myapp.
- Запуск без интервала. Просто pidstat покажет средние с момента загрузки - то есть бесполезную "историю". Всегда давай интервал: pidstat 1.
- Путаница %wait и iodelay. %wait - это ожидание процессора (стоял в runqueue), а не диска. Ждёшь диск - смотри iodelay в -d.
- Испуг от VSZ. Виртуальный размер в гигабайтах - норма для JVM и Go (резервируют адресное пространство впрок). Реальное потребление - это RSS.
- majflt/s высокий, а swap пуст. Это не обязательно своп. Мажорные faults бывают и без свопа: процесс читает большой mmap-нутый файл (например, JVM подгружает классы/jar после деплоя, или БД маппит файлы данных) и страницы вытесняются из pagecache под давлением памяти. Смотри связку: pidstat -r (majflt/s) плюс free -m (сколько buff/cache) плюс vmstat 1 (колонки si/so - своп, bi - чтение блоков). Если si/so по нулям, а bi скачет - дело в pagecache и mmap, а не в свопе.
- Забыл sudo для -d. Без root чисел по дисковому io по чужим процессам не увидишь.
- Только pidstat без контекста. pidstat говорит, КТО ест ресурс. Чтобы понять, НАСЫЩЕН ли сам ресурс, нужна связка: vmstat 1 (общая картина CPU/память/swap/runqueue), iostat -x 1 (загрузка дисков, %util, await, aqu-sz). Сначала vmstat/iostat показывают, ЧТО узкое место, потом pidstat - КТО конкретно его создаёт.
- Где pidstat упирается в потолок. pidstat выдаёт агрегаты по процессу за интервал. Если нужно знать, на КАКОМ именно сисколле или функции залипает процесс, или ловить короткоживущие процессы, которые pidstat не успевает заметить, - в 2026 это территория eBPF: bpftrace и bcc-инструменты (execsnoop для коротких процессов, biosnoop/biolatency для дисковых задержек, offcputime для анализа времени вне CPU). Они зрелые, работают на ядрах 5.x и новее и почти вытеснили strace/старый perf для точечной диагностики из-за низких накладных расходов. pidstat остаётся первым, быстрым шагом; eBPF - вторым, прицельным.
- Поставь sysstat, если его нет, и проверь версию: pidstat -V.
- Запусти pidstat 1 5 и просто посмотри на живые строки %CPU, %usr, %system.
- В соседнем терминале создай нагрузку на CPU: yes > /dev/null & - и поймай этот процесс в pidstat по %usr и %CPU (он будет около 100%). Потом убей: kill %1.
- Создай дисковую запись: dd if=/dev/zero of=/tmp/test bs=1M count=2000 oflag=direct - и поймай dd в sudo pidstat -d 1 по kB_wr/s. Удали /tmp/test.
- Запусти pidstat -w 1 и сравни cswch/s у спокойного процесса (rsyslogd) и nvcswch/s у нагрузочного yes.
- Возьми любой многопоточный процесс (например pidof java) и разверни его на потоки: pidstat -t -p <PID> 1 - найди самый горячий TID.
- Чем интервальная метрика pidstat 1 принципиально честнее, чем колонка %CPU в ps по тому же процессу?
- Процесс показывает majflt/s = 200 и растущий, RSS большой, но swap пустой по free. О какой проблеме это говорит и какими ещё командами ты это подтвердишь?
- В чём разница между cswch/s и nvcswch/s, и какой из них растёт при нехватке ядер?
- Диск загружен на 100% по iostat -x. Какой командой pidstat ты найдёшь конкретного виновника и что в её выводе значит iodelay?
pidstat из пакета sysstat - твой главный инструмент атрибуции ресурса процессу во времени. Всегда запускай с интервалом: первая строка без интервала - бесполезное среднее с загрузки. Четыре рабочих режима: без флага - CPU (%usr, %system, %wait, %CPU), -d - диск (kB_rd/s, kB_wr/s, iodelay), -r - память и page faults (majflt/s, RSS), -w - контекстные переключения (cswch/s, nvcswch/s). Добавь -t для потоков и -C/-l для фильтрации. Читай не команды, а их колонки: цифры без интерпретации бесполезны. Помни маршрут: vmstat/iostat говорят, что перегружено, pidstat - кто это сделал, а eBPF (bpftrace, bcc) - почему именно, на уровне сисколлов и функций. Это и есть честный мониторинг процессов linux в 2026 году.