Диагностика CPU по ядрам: vmstat и mpstat

Рейтинг: 57.8% · 13 голосов
Подробный курс по диагностике и производительности Linux для админов и DevOps: с чего начать, методология USE, логи (journalctl, dmesg), процессы, CPU, память и OOM, диск и IO (iostat), сеть (ss, tcpdump), системные вызовы и strace, ltrace, perf, флеймграфы, ftrace, eBPF и bpftrace, lsof, мониторинг. Разбор каждого инструмента с чтением вывода.
Ответить
Аватара пользователя
Dmitry_SRE
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Диагностика CPU по ядрам: vmstat и mpstat

Сообщение Dmitry_SRE »

Оглавление курса (47)
  1. С чего начать диагностику Linux: методология вместо паники
  2. Первые 60 секунд: экспресс-диагностика нагруженного сервера
  3. Методологии диагностики: USE, RED и здравый смысл
  4. Логи systemd через journalctl: где искать причину
  5. Где лежат логи Linux: /var/log, dmesg и rsyslog
  6. Источники правды: load average, /proc и /sys
  7. Процессы Linux: ps, pstree и состояния процессов
  8. Интерактивный мониторинг: top и htop
  9. Метрики процессов во времени: pidstat
  10. Приоритеты и ограничения: nice, ionice, cgroups
  11. Сигналы и зависшие процессы: kill, и что делать с D-state
  12. Загрузка CPU: user, system, iowait, steal и контекст-свитчи
  13. Диагностика CPU по ядрам: vmstat и mpstat (вы здесь)
  14. Профилирование CPU: perf top и поиск пожирателя
  15. Частоты, троттлинг и NUMA: turbostat и numastat
  16. Память Linux: RSS, VSZ, page cache и миф о нехватке памяти
  17. Сколько памяти занято: free, /proc/meminfo и vmstat
  18. Поиск утечек и пожирателей памяти: smem, pmap, smaps
  19. Swap и подкачка: swapon, swappiness, когда своп - это боль
  20. OOM killer: кто и за что убил процесс
  21. Память ядра и slab: slabtop и куда уходит RAM
  22. Подсистема ввода-вывода: путь запроса от приложения до диска
  23. Диагностика диска: iostat и чтение await, %util
  24. Кто грузит диск: iotop и атрибуция io процессам
  25. Файловые системы: df, du, иноды и куда делось место
  26. Глубокая диагностика блочного слоя: blktrace и biolatency
  27. Кеш страниц и грязные данные: dirty pages, fsync, drop_caches
  28. Сетевой стек Linux: путь пакета и где возникают задержки
  29. Сокеты и соединения: ss и netstat
  30. Захват трафика: tcpdump для диагностики сети
  31. Задержки и потери в сети: ping, mtr, диагностика латентности
  32. Сеть как источник проблем: nftables, conntrack, дропы
  33. Что такое системный вызов и зачем его трассировать
  34. strace: трассировка системных вызовов на практике
  35. strace в бою: почему программа висит, падает или тормозит
  36. ltrace: трассировка вызовов библиотек
  37. Накладные расходы трассировки и безопасные альтернативы
  38. perf: универсальный профайлер Linux
  39. Флеймграфы: визуализация профиля производительности
  40. Трассировка ядра: ftrace и trace-cmd
  41. eBPF: революция в наблюдаемости Linux
  42. Инструменты eBPF на практике: BCC и bpftrace
  43. lsof: открытые файлы, дескрипторы, кто держит файл и порт
  44. Разбор кейса: приложение тормозит - пошаговая диагностика
  45. Непрерывный мониторинг: sar, node_exporter, Grafana, Zabbix
  46. Диагностика в контейнерах: cgroups, лимиты, Docker и Kubernetes
  47. Карта инструментов и сквозной разбор инцидента производительности
Знакомая картина: пользователи жалуются, что сайт тормозит, ты заходишь на сервер по ssh и видишь load average под потолком. Дальше у новичка обычно ступор - load большой, а что именно болит? Процессор? Диск? Память уехала в своп? Сосед по гипервизору? В этом уроке мы научимся за тридцать секунд отделять одно от другого парой простых утилит, которые есть почти в любом дистрибутиве, и сразу покажем, чем их дополняют современные средства 2026 года. Это базовый навык, без которого нагрузка на сервер linux так и останется для тебя черным ящиком.

Главная мысль урока проста: load average врет про причину. Он показывает усредненную за 1, 5 и 15 минут длину очереди задач, но не говорит, кто эту очередь создал, и сильно сглажен по времени. Хуже того, в Linux в load average попадают не только процессы, ждущие CPU, но и процессы в состоянии непрерываемого сна (D-state) - те, что висят на диске или NFS. Поэтому load 20 на 4 ядрах может быть и чистым CPU, и зависшим диском. А вот vmstat и mpstat показывают честную раскадровку - на что реально уходит каждая секунда работы CPU и сколько процессов толпится в очереди на исполнение прямо сейчас.

Как устроена нагрузка на CPU и при чем тут run queue

Представь кассу в магазине. Ядро процессора - это касса, а процессы (точнее потоки) - покупатели. В каждый момент касса обслуживает ровно одного. Остальные, кто готов платить прямо сейчас, стоят в очереди. Вот эта очередь готовых-к-работе задач и называется run queue. Если у тебя 4 ядра (4 кассы), то 4 покупателя обслуживаются одновременно, и это нормально. А если в очереди стабильно висит 12 готовых задач на 4 ядра - касс не хватает, система в насыщении (saturation). Каждая задача ждет своей доли CPU, растет задержка планировщика, и все тормозит, хотя сами ядра при этом загружены на 100% и работают изо всех сил.

Ключевое слово - готовых. Задача, которая спит в ожидании ответа от диска или сети, в run queue НЕ стоит. Она в блокировке. Поэтому большой run queue - это именно нехватка процессора, а не диска. Это и есть простое правило, которое мы будем проверять: сравниваем число в колонке r с количеством ядер. Узнать число ядер легко:

Код: Выделить всё

nproc
# или подробнее, с разбивкой на сокеты/ядра/потоки
lscpu | grep -E "^CPU\(s\)|Core|Socket|Thread"
Важный нюанс на 2026: nproc и колонка r считают логические процессоры, то есть с учетом Hyper-Threading/SMT. Восемь физических ядер с SMT - это 16 логических, и порог насыщения по r надо брать именно 16. Но помни, что два потока на одном физическом ядре не дают двойной производительности (реально плюс 20-30 процентов), поэтому r=16 на 8 физических ядрах ощущается тяжелее, чем кажется. Запомни число логических ядер - это твой порог, дальше все измерения сверяем с ним.

Изображение

vmstat linux: читаем по колонкам и ловим насыщение

Запускать vmstat без аргументов почти бесполезно: первая строка - это средние с момента загрузки сервера, мусор для диагностики. Нам нужна динамика в реальном времени, поэтому добавляем интервал в секундах:

Код: Выделить всё

vmstat 1
Команда печатает новую строку каждую секунду, пока не нажмешь Ctrl+C. Полезный флаг -w (wide) расширяет колонки, чтобы большие числа не слипались, а -t добавляет столбец с временем - удобно класть в лог:

Код: Выделить всё

vmstat -w -t 1
Если хочешь снять ровно 60 замеров и выйти (например, под нагрузочный тест на минуту), задай второй аргумент - число повторов: vmstat 1 60. Первую напечатанную строку всегда игнорируй, смотри со второй. Вот типичный вывод:

Код: Выделить всё

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 8  0      0 201160  88540 1340220    0    0     0    16 5210 9300 78 12  9  1  0
 9  1      0 200980  88540 1340220    0    0     0     0 5102 9011 81 11  8  0  0
Разберем по группам, слева направо. Группа procs:
  • r - сколько задач готовы выполняться: либо уже на CPU, либо ждут в run queue. Здесь 8 и 9. Если у нас 4 логических ядра, а r стабильно держится 8-9 - это насыщение, процессора не хватает вдвое.
  • b - сколько процессов в непрерываемом сне (uninterruptible sleep, состояние D). Чаще всего это ожидание ввода-вывода: диск, NFS, иногда блокировки в ядре. Если b постоянно больше нуля - смотри в сторону диска или сети, а не CPU. Тонкость: b - это не "ждут CPU", а именно "застряли в ядре", их легко спутать с r.
Группа swap - это первое, что я проверяю всегда:
  • si - сколько килобайт в секунду подкачивается ИЗ свопа в память (swap in).
  • so - сколько уходит В своп (swap out).
В норме si и so - нули. Если они ненулевые и держатся - тревога: памяти не хватает, ядро гоняет страницы на диск и обратно, и любой профайлинг CPU теряет смысл, потому что узкое место в памяти. Сначала лечи своп. Оговорка на 2026: разовый ненулевой so при свежей загрузке часто безобиден - ядро лениво вытесняет давно неиспользуемые страницы. Опасен именно устойчивый поток si+so одновременно: это значит, что рабочий набор не влезает в RAM и страницы постоянно ходят туда-обратно (thrashing).

Группа system:
  • in - прерываний в секунду (interrupts). Аппаратные сигналы от сетевой карты, диска, таймера.
  • cs - переключений контекста в секунду (context switches). Сколько раз в секунду планировщик переключал ядро CPU с одной задачи на другую.
Сами по себе десятки тысяч cs и in - норма для нагруженного сервера. Тревожный признак - когда cs резко взлетает на ровном месте при том же объеме работы: это часто грызня за блокировки (lock contention), слишком много потоков, дерущихся за CPU, или busy-loop. Полезное правило: высокий cs при высоком sy и невысоком us - запах того, что приложение жжет время на синхронизацию, а не на полезную работу.

Группа cpu - проценты, в сумме всегда дают 100:
  • us (user) - время на код приложений в пользовательском пространстве. Высокий us - работает твой код: PHP, Python, JVM, расчеты. Это "хорошая" загрузка, если она оправдана.
  • sy (system) - время в ядре: системные вызовы, работа с сетью и файлами. Аномально высокий sy - подозрение на шквал syscall'ов, сетевой флуд или неэффективный код.
  • id (idle) - процессор простаивает. Если тут стабильный 0 - CPU выжат досуха.
  • wa (iowait) - CPU простаивает, потому что ждет диск. Высокий wa = узкое место в диске, а не в процессоре. Важно понимать, что iowait - это разновидность idle: ядро не занято, оно просто ждет io, и эти такты можно было бы отдать другой задаче, если бы она была.
  • st (steal) - украденное время. Актуально на виртуалках и в облаке: гипервизор отдал твои такты соседу. Ненулевой st на VPS означает, что сосед по железу объедает тебя.
Итак, рецепт диагностики по vmstat. Видишь высокий r относительно числа ядер и при этом высокий us - классика, чистая нехватка CPU под прикладной нагрузкой. Видишь высокий wa и/или b - беги к диску (iostat, урок про io). Видишь ненулевые si/so - проблема в памяти. Видишь высокий st - жалуйся хостеру или переезжай на другой тариф. Одна команда - и направление поиска найдено.

mpstat: ловим дисбаланс по ядрам

vmstat показывает CPU целиком, одной усредненной строкой. И тут прячется коварная ловушка. Допустим, у тебя 8 ядер. Одно ядро забито на 100%, остальные семь спят. Усреднение даст примерно 12% - и vmstat покажет, будто процессор почти свободен. А приложение при этом стоит колом, потому что уперлось в одно ядро. Чтобы это увидеть, нужна разбивка по каждому ядру. Ее дает mpstat (пакет sysstat, ставится как sysstat в apt/dnf):

Код: Выделить всё

mpstat -P ALL 1
Флаг -P ALL означает per processor, all - показать каждое логическое ядро отдельной строкой плюс строку all со средним. Интервал 1 - обновление раз в секунду. Вывод:

Код: Выделить всё

CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
all   13.20    0.00    1.50    0.10    0.00    0.30    0.00    0.00    0.00   84.90
  0   99.00    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
  1    1.00    0.00    0.50    0.00    0.00    0.00    0.00    0.00    0.00   98.50
  2    0.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00   99.00
Смотри, что говорят строки. Строка all дает среднее: 84.9 процента idle - вроде бы все прекрасно. Но строка CPU 0 показывает %usr 99 и %idle 0 - ядро ноль в полке, наглухо. Остальные ядра почти на 99 процентов idle, то есть курят в сторонке. Это и есть дисбаланс. Среднее обмануло, а разбивка вскрыла правду.

Поля mpstat детальнее, чем cpu-группа vmstat, и это его сила:
  • %usr - пользовательский код, %nice - то же, но процессы с пониженным приоритетом (nice), %sys - ядро, %idle - простой, %iowait - ожидание диска, %steal - украдено гипервизором.
  • %irq и %soft - обслуживание аппаратных и программных прерываний (softirq). Высокий %soft именно на одном-двух ядрах - классический симптом, когда все прерывания сетевой карты привязаны к этим ядрам. На сетевом сервере смотри сюда первым делом.
  • %guest и %gnice - время на исполнение виртуальных CPU (актуально на хосте гипервизора, на обычной VM это нули).
Что означает одно ядро в полке на практике? Два типичных диагноза. Первый - однопоточное узкое место: программа умеет грузить только один поток (однопоточный скрипт, тяжелый regexp, GIL в Python, неудачная конфигурация воркеров). Добавлять ядра бесполезно, нужно распараллеливание. Второй - привязка прерываний: весь сетевой трафик летит на одно ядро, потому что не настроен RSS на сетевой карте или отключен/неудачно настроен irqbalance. Тогда под нагрузкой именно это ядро захлебывается в %soft. Проверить распределение прерываний можно так: cat /proc/interrupts и mpstat -I SUM -P ALL 1 (флаг -I показывает статистику по прерываниям).

Что нового в 2026: PSI и eBPF поверх классики

vmstat и mpstat живы и прекрасно работают, но в современном ядре (cgroup v2 по умолчанию во всех актуальных дистрибутивах - Ubuntu, Debian, RHEL-семейство, Astra Linux, RED OS) появились средства точнее. Самое полезное на 2026 - PSI, Pressure Stall Information. Это встроенный в ядро счетчик, который прямо отвечает на вопрос "насколько система задыхается из-за нехватки CPU", без гадания по r:

Код: Выделить всё

cat /proc/pressure/cpu
Вывод вроде some avg10=12.30 avg60=8.10 avg300=2.40 total=.... Значение some avg10=12.30 читается так: за последние 10 секунд примерно 12.3 процента времени хотя бы одна задача стояла в очереди и ждала CPU, который был занят. Ноль - всем хватает процессора. Растущие десятки процентов - реальное насыщение, причем PSI учитывает именно ожидание, а не просто загрузку. То же есть для памяти и io (/proc/pressure/memory, /proc/pressure/io), а в cgroup v2 у каждого контейнера/сервиса есть свои cpu.pressure, memory.pressure, io.pressure - можно ткнуть пальцем в конкретный systemd-юнит. Это то, на что стоит смотреть в первую очередь в 2026, особенно в контейнерах.

Когда надо понять не "сколько" задач в очереди, а "как долго" каждая ждет, на сцену выходит eBPF. Инструменты runqlat и runqlen (из пакетов bpftrace или bcc-tools, в свежих дистрибутивах ставятся штатно) дают то, чего нет у vmstat:
  • runqlat - гистограмма задержки планировщика (run queue latency): сколько микросекунд задача ждала своей очереди на CPU. Если хвост гистограммы уезжает в миллисекунды - планировщик не успевает, CPU перегружен, и это видно в цифрах задержки, а не косвенно.
  • runqlen - гистограмма длины очереди по каждому ядру, семплируется на 99 Гц. Прямо показывает дисбаланс: на одном ядре очередь, на другом пусто.
eBPF в 2026 - зрелая технология: для базовой диагностики CPU он не заменяет vmstat/mpstat (те быстрее набрать и они есть везде), но дополняет их там, где нужна точность по задержке. Стартуй с vmstat и PSI, углубляйся через runqlat, когда классика показала перегрузку, но не объясняет, насколько она бьет по latency.

sar: смотрим в прошлое, когда инцидент уже прошел

vmstat и mpstat хороши, когда проблема прямо сейчас перед глазами. А если ночью сервер задыхался, а к утру отпустило? Тут спасает sar из того же пакета sysstat - он пишет историю в фоне. Если служба сбора включена, данные пишутся автоматически каждые несколько минут. Посмотреть нагрузку CPU за сегодня:

Код: Выделить всё

sar -u
# конкретный диапазон времени
sar -u -s 02:00:00 -e 04:00:00
# за конкретную дату (файлы лежат в /var/log/sa/ или /var/log/sysstat/)
sar -u -f /var/log/sa/sa14
# разбивка по ядрам из истории
sar -P ALL
Колонки sar -u те же, что у mpstat: %user, %nice, %system, %iowait, %steal, %idle. Так ты увидишь, в котором часу %idle падал в пол, и сопоставишь с жалобами. На свежей установке sar часто молчит, потому что сбор выключен. Включается так:

Код: Выделить всё

sudo systemctl enable --now sysstat
На Astra Linux и RED OS sysstat ставится из штатных репозиториев так же, имена пакетов и утилит совпадают - тут все стандартно. На 2026 многие площадки уже держат метрики в Prometheus + node_exporter (он отдает и node_pressure_cpu_*, то есть PSI), а sar остается простым локальным запасным вариантом без отдельной инфраструктуры.

Типичные грабли и заблуждения
  • Верить load average про причину. Load 20 на 4 ядрах может быть и из-за CPU, и из-за зависшего диска: процессы в состоянии D попадают в load, но это не процессор. Всегда проверяй vmstat: высокий r - это CPU, высокий b и wa - это io.
  • Читать первую строку vmstat. Она усреднена с момента загрузки и не отражает текущий момент. Смотри со второй строки.
  • Доверять усреднению. Главная причина, по которой одной vmstat недостаточно. Всегда добавляй mpstat -P ALL, чтобы не пропустить ядро в полке за красивым средним.
  • Забывать про SMT. Порог по r считай по логическим ядрам (nproc), но помни, что SMT-потоки не равны полноценным ядрам, и реальное насыщение наступает чуть раньше.
  • Игнорировать st на виртуалке. Если в облаке тормозит, а us/sy низкие - смотри %steal. Это не твоя вина, это сосед или переподписка хостера.
  • Путать b и r. r - готовы работать (нужен CPU). b - застряли в непрерываемом сне на io (нужен диск/сеть). Это разные болезни и разное лечение.
  • Не смотреть PSI в контейнерах. На 2026 cpu.pressure конкретного cgroup точнее покажет, какой именно сервис душит CPU, чем общесистемный vmstat.
Мини-лаба: повтори руками прямо сейчас
  • Узнай число логических ядер: nproc. Запиши.
  • Открой два терминала. В первом запусти vmstat 1, во втором mpstat -P ALL 1.
  • Создай нагрузку на одно ядро:

    Код: Выделить всё

    yes > /dev/null &
    Посмотри в mpstat - одно ядро уйдет в %usr под 100, остальные останутся в idle. Вот он, дисбаланс, своими глазами. Параллельно глянь

    Код: Выделить всё

    cat /proc/pressure/cpu
    - some avg10 поползет вверх.
  • Запусти нагрузку на все ядра (по числу из nproc, например 4):

    Код: Выделить всё

    for i in $(seq 4); do yes > /dev/null & done
    Теперь смотри vmstat: колонка r поднимется к числу ядер и выше, id упадет в 0. Это и есть наполнение run queue.
  • Если установлены bpftrace или bcc-tools, в третьем терминале запусти

    Код: Выделить всё

    sudo runqlat 5 1
    и посмотри, как растет задержка планировщика под нагрузкой.
  • Обязательно прибей фоновые процессы, чтобы не жгли CPU зря:

    Код: Выделить всё

    pkill yes
Контрольные вопросы
  • У тебя 8 логических ядер, а колонка r в vmstat стабильно держит 24. О чем это говорит и куда копать?
  • vmstat показывает %idle около 90, но приложение жестко тормозит. Какой утилитой и каким флагом ты проверишь, не упирается ли все в одно ядро?
  • Колонки si и so в vmstat показывают устойчивые ненулевые значения. Имеет ли смысл дальше профилировать CPU и почему?
  • Чем принципиально отличается колонка r от колонки b в группе procs и что показывает /proc/pressure/cpu по сравнению с ними?
Что запомнить

vmstat 1 - твой первый взгляд на систему: run queue (r) против числа логических ядер ловит насыщение CPU, si/so ловят своп, wa и b ловят диск, st ловит проблемы виртуализации. mpstat -P ALL 1 вскрывает дисбаланс по ядрам, который усреднение прячет: одно ядро в полке при общем низком потреблении - это либо однопоточное узкое место, либо привязка прерываний (%soft). sar -u дает историю, чтобы разобрать инцидент задним числом. А на 2026 поверх этой классики стоит /proc/pressure/cpu (PSI) для прямой оценки давления на CPU и runqlat/runqlen на eBPF для точной задержки планировщика. Освоишь эти команды - и нагрузка на сервер перестанет быть загадкой.
👍3 ❤️5 🔥1 😄 🤔3
Аватара пользователя
njgreen
Сообщения: 1
Зарегистрирован: 15 май 2026, 08:02

Re: Диагностика CPU по ядрам: vmstat и mpstat

Сообщение njgreen »

Спасибо, до этого вообще не понимал разницу между r и b, думал это одно и то же про очередь. Опыт с yes > /dev/null прям наглядно зашел, увидел ядро в полке своими глазами. Про /proc/pressure/cpu впервые слышу, побежал смотреть на своих контейнерах.
👍 ❤️ 🔥1 😄 🤔
Аватара пользователя
cpp_wizard
Сообщения: 1
Зарегистрирован: 25 май 2026, 23:24

Re: Диагностика CPU по ядрам: vmstat и mpstat

Сообщение cpp_wizard »

А подскажите, у меня на VPS %steal стабильно 15-20 держится, vmstat по CPU вроде чистый, us невысокий, а тормозит. Это уже повод писать хостеру или норма для дешевого тарифа? И PSI на VM вообще считает steal как давление или нет?
👍1 ❤️1 🔥1 😄 🤔
Ответить
← Предыдущая глава
Загрузка CPU: user, system, iowait, steal и контекст-свитчи
Следующая глава →
Профилирование CPU: perf top и поиск пожирателя

Все главы курса «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Поделиться темой: ✈ Telegram VK
Похожие запросы: как посмотреть сколько памяти занято в linuxss как посмотреть открытые сокеты и соединенияstrace почему программа висит и тормозитperf top как найти что грузит процессорЛоги и диагностика macOSкак посмотреть процессы в linux и убить зависший

Вернуться в «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость