Производительность и устранение неполадок

Системная методика: как по нагрузке, памяти, диску и системным вызовам быстро локализовать, что именно тормозит сервер.

Узкое место (bottleneck) — ресурс (CPU, память, диск или сеть), исчерпание которого ограничивает производительность всей системы. Диагностика — это поиск того, какой из четырёх ресурсов «упёрся».

Зачем это на практике

«Сервер тормозит» — самая частая и самая расплывчатая жалоба. Без метода легко часами смотреть не туда. Цель урока — дать порядок действий: сначала понять, какой ресурс в дефиците (CPU/RAM/диск/сеть), и только потом искать виновный процесс конкретным инструментом. Угадывание заменяется измерением.

Load average: первый сигнал

Три числа в uptime — средняя длина очереди готовых к работе процессов за 1, 5 и 15 минут. Сравнивать их нужно с числом ядер:

uptime
nproc                     # сколько ядер
cat /proc/loadavg

Вывод:

15:42:10 up 8 days,  load average: 3.40, 2.10, 1.05

Если ядер 4, то load 3.40 — это ~85% загрузки, ещё норма. Load 8.0 на 4 ядрах — система перегружена, процессы стоят в очереди. Тренд важнее точки: 3.40, 2.10, 1.05 означает растущую нагрузку (1-минутное больше 15-минутного) — что-то началось недавно.

htop / top: живая картина

top есть везде, htop удобнее (цвета, прокрутка, дерево). Что читать в первую очередь:

  • строка %Cpu(s): us — пользовательский код, sy — ядро, waожидание диска (высокий wa = упёрлись в I/O, а не в CPU), id — простой.
  • сортировка по CPU (клавиша P) и по памяти (M) — кто жрёт ресурс.
  • колонка S (state): R — выполняется, Dнепрерываемый сон (ждёт диск/сеть, плохой признак при массовости).
htop                  # F4 фильтр, F6 сортировка, F9 послать сигнал
top -o %MEM           # сразу сортировать по памяти

free: память и swap

Главная ловушка новичка — пугаться «занятой» памяти. Linux намеренно держит кэш, поэтому смотреть нужно на колонку available, а не free:

free -h

Вывод:

               total        used        free      shared  buff/cache   available
Mem:            15Gi       4.2Gi       0.5Gi       0.3Gi        10Gi        10Gi
Swap:          2.0Gi       0.1Gi       1.9Gi

Здесь free всего 0.5 Gi, но available — 10 Gi: 10 Gi занято под buff/cache, который ядро мгновенно отдаст приложениям. Реальная проблема — когда мал именно available и активно растёт used у swap (система свопится → дисковые тормоза).

vmstat и iostat: CPU vs диск

Когда wa высокий, нужно подтвердить, что виноват диск. vmstat даёт сводку по системе с интервалом, iostat (пакет sysstat) — детально по дискам:

vmstat 2 5            # каждые 2 секунды, 5 раз
#  колонки si/so = свопится ли (ненулевые = беда)
#  колонки bi/bo = блоков с/на диск; wa = ожидание I/O

iostat -xz 2          # -x подробно, -z скрыть пустые устройства

В iostat ключевые показатели: %util (близко к 100% — диск насыщен), await (время отклика, миллисекунды; растёт — диск не справляется), r/s и w/s (операций в секунду).

Поиск виновного: lsof и strace

Ресурс определили — теперь найти процесс и понять, что он делает. lsof отвечает «кто держит файл/порт», strace — «какие системные вызовы делает процесс» (и где он застрял):

# кто слушает порт 8080 / держит файл
sudo lsof -i :8080
sudo lsof /var/log/myapp.log
sudo lsof -p 12345 | head      # все дескрипторы процесса

# на чём висит процесс прямо сейчас
sudo strace -p 12345           # подключиться к работающему процессу
sudo strace -f -e trace=open,read,write ./script.sh   # -f включая потомков
strace -c ./program            # -c сводка: какие вызовы и сколько времени

strace -c бесценен, когда программа «зависает»: сводка покажет, в каком вызове (например read из сети или futex на блокировке) тратится всё время.

Методология диагностики

Чтобы не метаться, держите чёткий порядок (упрощённый USE-метод — Utilization, Saturation, Errors):

ШагВопросИнструмент
1Система вообще перегружена?uptime, top
2CPU или ожидание диска (us vs wa)?top, vmstat
3Хватает памяти, не свопится?free -h, vmstat (si/so)
4Диск не насыщен?iostat -xz
5Какой процесс виновен?htop, lsof
6Что он делает / где висит?strace, логи (journalctl)

Как это работает под капотом

load average считается ядром не как «загрузка CPU», а как число процессов в состоянии R (готов/выполняется) плюс D (непрерываемый сон, обычно ожидание диска) — поэтому система с простаивающим CPU, но медленным диском, всё равно покажет высокий load. Это объясняет, почему высокий wa и высокий load часто идут вместе. buff/cache в free — это страничный кэш: ядро держит недавно прочитанные с диска данные в свободной памяти, чтобы повторное чтение шло из RAM; как только приложению нужна память, кэш вытесняется мгновенно, поэтому он и считается «доступным». strace работает через системный вызов ptrace: ядро останавливает целевой процесс на каждом syscall и передаёт трассировщику аргументы — отсюда и его замедляющий эффект, и способность показать точку «зависания».

Частые ошибки

  • Паника из-за «занятой памяти», хотя это buff/cache; смотреть надо available.
  • Сравнивают load average без учёта числа ядер: 4.0 — катастрофа на 1 ядре и норма на 8.
  • Видят 100% «нагрузки» и сразу винят CPU, не посмотрев wa — а реально упёрлись в диск (I/O).
  • Запускают strace на нагруженном проде на постоянке: ptrace заметно тормозит процесс; используйте точечно и недолго.
  • Смотрят мгновенный снимок top один раз вместо интервальных vmstat 2 и делают вывод по случайному пику.

Итоги

  • Диагностика — это поиск исчерпанного ресурса: CPU, память, диск или сеть.
  • load average сравнивают с числом ядер и смотрят на тренд (1 vs 15 минут).
  • wa в top и si/so в vmstat отличают «упёрлись в диск/своп» от «упёрлись в CPU».
  • В free -h ориентир — available, а не free.
  • lsof находит держателя файла/порта, strace -c показывает, где процесс висит.
  • Держите порядок шагов (USE), а не угадывайте.
Проверьте себя
1. В top нагрузка близка к 100%, но колонка %Cpu показывает высокий wa и низкий us. Что это означает?
AПроцессор перегружен вычислениями, нужно больше ядер
BСистема упёрлась в ввод-вывод (ожидание диска), а не в CPU
CЗакончилась оперативная память
DПроизошла ошибка ядра
2. free -h показывает available 10Gi, но free всего 0.5Gi, при этом buff/cache 10Gi. Опасно ли это?
AДа, память почти закончилась, нужно срочно добавить RAM
BНет: buff/cache — это страничный кэш, ядро отдаст его приложениям при необходимости; ориентир — available
CДа, система вот-вот начнёт убивать процессы через OOM
DЭто всегда означает утечку памяти
3. Процесс с PID 12345 завис. Какой инструмент покажет, на каком системном вызове он остановился?
Afree -p 12345
Blsmod 12345
Cstrace -p 12345
Duptime 12345