Когда сервер «тормозит», первый вопрос — какая именно подсистема упёрлась в потолок: CPU, диск, память или сеть. Профилирование — это не гадание, а последовательный обход этих четырёх точек с конкретными командами и конкретными числами в выводе.
Базовые инструменты диагностики
| Инструмент | Что показывает | Установка |
|---|---|---|
| top / htop | CPU, RAM, процессы | htop (apt) |
| iostat | Дисковый I/O | sysstat (apt) |
| vmstat | Память, swap, CPU | procps (встроен) |
| netstat / ss | Сетевые соединения | net-tools / iproute2 |
| iotop | Топ процессов по I/O | iotop (apt) |
| dstat | Всё в одном | dstat (apt) |
Диагностика высокого CPU
# Найти процесс с максимальной нагрузкой
top -b -n 1 | head -20
# Посмотреть что делает процесс
strace -p PID -c
# Flamegraph (если установлен perf)
perf record -g -p PID sleep 30
perf script | stackcollapse-perf.pl | flamegraph.pl > cpu.svg
Отдельно стоит смотреть load average против числа ядер: nproc покажет их количество, и если первое число из uptime держится заметно выше этого числа часами, а не минутами, — это уже не всплеск, а систематическая нехватка CPU, и профилирование одного процесса не заменит апгрейд или оптимизацию кода.
Диагностика медленного диска
# I/O статистика по устройствам
iostat -x 1 5
# Какой процесс нагружает диск
iotop -o -b -n 5
# Проверка состояния RAID / SMART
smartctl -a /dev/sda
В выводе iostat -x ключевая колонка — %util: значение, близкое к 100%, означает, что устройство занято почти постоянно, а колонка await показывает среднюю задержку запроса в миллисекундах — рост await при неизменном util обычно указывает на деградацию самого диска, а не просто рост нагрузки.
Диагностика нехватки памяти
# Сводка по памяти
free -h
# Топ процессов по RAM
ps aux --sort=-%mem | head -10
# OOM killer лог (кто был убит)
dmesg | grep -i "killed process"
Разбор типичных сообщений и метрик
Строка Out of memory: Killed process 4821 (mysqld) total-vm:2145728kB в выводе dmesg — это не ошибка mysqld, а решение ядра: OOM killer выбрал процесс с наибольшим потреблением памяти и принудительно завершил его, чтобы не допустить полного зависания системы. После такого события нужно смотреть, что стало причиной роста потребления — утечка, неудачный запрос или просто нехватка RAM под текущую нагрузку, а не просто перезапускать сервис.
Высокий %wa (iowait) в top при низком %us и %sy означает, что процессор простаивает не потому, что ему нечего делать, а потому что ждёт ответа от диска. Апгрейд CPU в такой ситуации не поможет — узкое место физически в дисковой подсистеме или в конкретном процессе с избыточным I/O, который находится через iotop.
Load average выше числа ядер при нормальном CPU и I/O — часто означает не вычислительную нагрузку, а очередь процессов, ожидающих недоступный ресурс: заблокированный файл, семафор или медленный внешний запрос (например, к базе данных или API). В такой ситуации ps aux покажет процессы в состоянии D (uninterruptible sleep) — именно они формируют load average, а не CPU-нагрузку.
Сравнение подходов к диагностике
| Подход | Глубина | Нагрузка на систему | Когда применять |
|---|---|---|---|
| top / htop / free / df | Поверхностная, снимок сейчас | Минимальная | Первая минута диагностики |
| iostat / vmstat в цикле | Средняя, тренд за минуты | Низкая | Подтвердить подозрение на диск или память |
| strace / iotop с фильтром по PID | Глубокая, конкретный процесс | Средняя, может замедлить процесс | Найти виновника среди десятков процессов |
| perf + flamegraph | Максимальная, стек вызовов | Заметная на CPU-bound нагрузке | Оптимизация конкретного кода, не разовая проверка |
Когда профилирования на самом сервере недостаточно
- Проблема проявляется редко и непредсказуемо — разовый запуск
topв момент затишья ничего не покажет, нужен постоянный сбор метрик вроде системы мониторинга с историей. - Узкое место не в самом VDS, а во внешней зависимости (медленный DNS, удалённое API, сетевой провайдер) — локальные инструменты покажут только то, что процесс «ждёт», но не объяснят, чего именно ждёт сеть снаружи сервера.
- Нагрузка распределена между несколькими серверами — профилирование одного VDS не увидит общую картину балансировки и перекоса нагрузки между узлами.
- Нужна точная причина деградации кода приложения, а не системных ресурсов, — здесь системные утилиты уступают APM-инструментам уровня приложения.
Проверка результата
- После применённой правки (индекс в базе, добавленный swap, изменённый конфиг) повторите тот же набор команд и сравните конкретные числа:
%utilдиска,load average,%wa— снижение должно быть измеримым, а не «на глаз стало быстрее». - Проверьте, что проблема не переместилась в другое место: снижение нагрузки на CPU иногда просто открывает дорогу очереди запросов к диску, которая раньше была не видна за более медленным CPU.
- Оставьте мониторинг включённым хотя бы сутки после изменения — разовая проверка сразу после правки не покажет поведение под вечерним или ночным пиком нагрузки.
- Зафиксируйте baseline метрик в спокойном состоянии — без опорных цифр «нормальной» нагрузки следующую проблему придётся диагностировать с нуля.