Этот урок - вводный для всего курса. Здесь не будет глубокого разбора флагов strace, perf или bpftrace - это всё дальше, по отдельным урокам. Сейчас важнее другое: научиться подступаться к проблеме. Когда у тебя в голове есть метод, диагностика linux перестаёт быть гаданием и превращается в нормальную инженерную работу - от симптома к причине, шаг за шагом. Новичок, который знает метод, обгонит "опытного", который просто помнит десять команд наизусть, но не понимает, что они меряют.
Почему linux тормозит: учимся не паниковать, а локализовать
Первое, что нужно принять: "linux тормозит" - это не диагноз, а жалоба. Точно так же, как "у меня болит" - это ещё не то, с чем врач может работать. Врач первым делом уточняет: где болит, когда началось, при каких движениях, постоянно или приступами. Мы делаем ровно то же самое. Прежде чем лезть в команды, сформулируй симптом конкретно: "ответ API вырос с 50 мс до 2 секунд начиная с 14:00" - это рабочая формулировка, а "всё лагает" - нет.
Любая проблема производительности в итоге упирается в одну из пяти подсистем:
- CPU - процессор не успевает считать, задачи стоят в очереди на выполнение (runqueue).
- Память (RAM) - не хватает оперативки, начинается swap или прилетает OOM killer и убивает процесс.
- Диск (I/O) - приложение ждёт чтения/записи, диск или сетевое хранилище - узкое место.
- Сеть - потери пакетов, ретрансмиты, упёрлись в полосу или в лимиты соединений/conntrack.
- Само приложение - блокировки, кривой код, нехватка воркеров, медленные запросы в БД, ожидание внешнего сервиса.

Узкое место и насыщение: главная идея производительности linux
Два слова, которые надо понять раз и навсегда: узкое место (bottleneck) и насыщение (saturation).
Представь трассу с платным пунктом оплаты. Сколько бы полос ни было до и после, скорость всего потока определяет самый узкий участок - шлагбаумы. Это и есть bottleneck. В системе так же: можно иметь 64 ядра и кучу памяти, но если все упёрлись в один медленный диск - тормозить будет всё, и апгрейд процессора не поможет ни на грамм. Поэтому бессмысленно "оптимизировать" то, что не является узким местом: ускорять CPU, когда система ждёт диск, - выкинутые деньги.
Утилизация (utilization) - насколько ресурс занят, в процентах. Диск был занят 90% времени - высокая утилизация.
Насыщение (saturation) - сколько работы стоит в очереди и ждёт, потому что ресурс не справляется. Вот это - самый честный признак боли. Процессор может показывать 100%, но если очередь на выполнение пустая - он просто эффективно работает, это нормально. А если очередь растёт - всё, началось насыщение, задачи ждут, и пользователь это чувствует как лаги. Запомни правило: высокая утилизация - это не всегда проблема, насыщение - почти всегда проблема.
На этой идее построен метод USE Брендана Грегга (Brendan Gregg) - инженера из Netflix, чьи материалы по производительности linux считаются классикой. USE расшифровывается как Utilization, Saturation, Errors. Для каждого ресурса задаём три вопроса:
- Utilization - насколько занят? (CPU в процентах, диск %util, память занято/свободно)
- Saturation - есть ли очередь, ждёт ли кто-то? (длина runqueue, очередь к диску, swap)
- Errors - есть ли ошибки? (в dmesg, в логах диска - bad sectors, дропы пакетов, ECC-ошибки памяти)
Актуально на 2026: раньше насыщение приходилось вычислять косвенно (по load average, по очереди в iostat). Теперь в ядре есть прямой и честный измеритель насыщения - PSI (Pressure Stall Information). Это файлы /proc/pressure/cpu, /proc/pressure/memory, /proc/pressure/io. Они показывают, какой процент времени задачи реально стояли и ждали ресурс. Поскольку современные дистрибутивы (свежие Ubuntu, Debian, RHEL/RED OS, Astra Linux на современных ядрах) перешли на cgroup v2 по умолчанию, PSI доступен и по системе целиком, и по каждому cgroup/контейнеру (файлы cpu.pressure, memory.pressure, io.pressure внутри cgroupfs). Глянем общесистемную память:
Код: Выделить всё
$ cat /proc/pressure/memory
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0
Карта инструментов: чем делать диагностику сервера linux
У Брендана Грегга есть знаменитая "карта инструментов" (Linux Performance Observability Tools) - картинка, где поверх схемы ядра Linux подписано, какая утилита что измеряет. Её реально стоит распечатать и повесить на стену. Идея простая: каждый инструмент смотрит в свою подсистему. Вот грубая привязка, которую держим в голове:
- Обзор всего - top, htop, btop, uptime, vmstat, /proc/pressure
- CPU - mpstat, pidstat, потом глубже perf, profile (bcc)
- Память - free, vmstat, /proc/meminfo, smem
- Диск - iostat, потом biolatency и biosnoop (bcc/bpftrace)
- Сеть - ss (вместо устаревшего netstat), sar -n DEV, потом tcpdump, conntrack, tcplife/tcpretrans
- Приложение - логи (journalctl), strace для разовой отладки, дальше eBPF: bpftrace, execsnoop, opensnoop
Сейчас не нужно знать их флаги. Нужно знать, куда смотреть в первую очередь. У того же Грегга есть рецепт "первые 60 секунд": десяток стандартных команд, которые за минуту дают общую картину. Тебе пока хватит вот этих:
Код: Выделить всё
uptime # средняя нагрузка (load average) за 1, 5, 15 минут
dmesg -T | tail # свежие ошибки ядра: OOM, сбои диска, паники (-T = человекочитаемое время)
vmstat 1 # общая динамика: CPU, память, swap, io - раз в секунду
free -h # сколько реально свободной памяти
df -h # не забит ли диск под завязку (частая причина падений)
df -i # не кончились ли inode (диск вроде есть, а файл не создаётся)
Код: Выделить всё
$ uptime
14:23:07 up 42 days, 3:15, 2 users, load average: 0.52, 1.20, 4.85
Теперь vmstat - одна из самых полезных команд для старта. Первая строка вывода - средние с момента загрузки, её игнорируй, смотри со второй:
Код: Выделить всё
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 198432 45120 890244 0 0 5 12 220 410 12 3 84 1 0
8 1 0 120100 45120 870100 0 0 240 5800 1500 3200 25 10 5 60 0
- r - сколько процессов выполняется или ждёт CPU. Если r стабильно больше числа ядер - процессор узкое место, очередь не рассасывается.
- b - сколько в непрерываемом сне (uninterruptible sleep, состояние D), почти всегда ждут диск. Ненулевой b вместе с высоким wa - однозначно I/O.
- si/so - swap in/out в КБ/с. Любые стабильно ненулевые значения здесь - тревога: системе не хватает памяти, она тасует страницы через диск, и это убивает производительность. Разовый одиночный so может быть безобидным, важна именно постоянная активность.
- bi/bo - блоки, прочитанные с диска и записанные на диск. Резкий рост bo при тормозах - идём смотреть, кто столько пишет.
- cs - context switches в секунду. Аномально высокий cs (десятки-сотни тысяч) при невысоком полезном us часто значит борьбу за блокировки или слишком много потоков.
- wa (группа cpu) - процент времени, что CPU простаивал в ожидании диска. В примере во второй строке wa=60 - процессор не считает, он ждёт диск. Классический признак: узкое место - I/O, а не CPU.
- us/sy/id - user/system/idle. Высокий us - грузит код приложения, высокий sy - грузит ядро (часто шквал системных вызовов или сетевой нагрузки).
- st - steal time. Критично для виртуалок и облака: это процент времени, когда твоя VM была готова считать, но гипервизор не дал ей CPU (его забрал сосед по железу). Ненулевой st на 2026 - очень частая причина "необъяснимых" тормозов в облаке, а внутри гостя все остальные метрики при этом могут выглядеть нормально.
Типичные грабли и заблуждения новичка
- Менять десять вещей сразу. Покрутил sysctl, перезапустил сервис, поправил конфиг, увеличил лимиты - и оно "заработало". А что именно помогло? Неизвестно. Завтра сломается снова, и ты не воспроизведёшь. Меняй по одному и проверяй эффект.
- Не фиксировать действия. Заведи привычку писать в тикет или блокнот: время, симптом, что увидел, что поменял, что стало. Это не бюрократия - это спасает, когда через час ты уже не помнишь, что трогал, и когда нужно откатить.
- ["100% CPU = беда".] Не обязательно. Если задача и должна молотить процессор, а очередь (r) маленькая и PSI по cpu около нуля - всё нормально, ресурс просто работает. Беда - это насыщение и рост очереди.
- Путать load average с загрузкой CPU. В Linux load включает и процессы в ожидании диска (состояние D). Высокий load при низком потреблении CPU и пустой runqueue - почти наверняка дисковая проблема, а не процессорная.
- Игнорировать steal time в облаке. В виртуалке смотри на st в vmstat и %steal в top. Внутри гость может казаться здоровым, а тормоза идут от соседей по гипервизору.
- Сразу лезть в strace/perf/bpftrace. Это мощные инструменты, но если ты не локализовал подсистему, они только утопят тебя в данных. Сначала общая картина (60 секунд + PSI), потом прицельное погружение.
- Забыть про df -h и df -i. Огромная доля "падений приложения" - это банально забитый под 100% диск или закончившиеся inode (файлов мало по объёму, но их много). Проверяй это в первую очередь, это 10 секунд.
Открой терминал на любой Linux-машине (рабочий сервер, домашняя VM, WSL2 - подойдёт всё; на Astra Linux и RED OS эти команды работают так же, пакет sysstat для sar/mpstat/iostat ставится из штатных репозиториев):
- Запусти uptime. Раздели каждое из трёх чисел load average на число ядер (узнать ядра: nproc). Прикинь, нагружена машина или отдыхает, растёт нагрузка или падает.
- Загляни в насыщение: cat /proc/pressure/cpu и cat /proc/pressure/io. Сейчас some почти наверняка около нуля - это "норма покоя". Запомни, как выглядит здоровье.
- Запусти vmstat 1, дай поработать секунд десять, нажми Ctrl+C. Найди глазами колонки r, b, wa, si, so, st. Сейчас они почти наверняка около нуля.
- Создай искусственную нагрузку на CPU и посмотри, как меняется картина. На число потоков по ядрам: stress-ng --cpu $(nproc) --timeout 20s (если stress-ng не установлен, грубый аналог - запустить yes > /dev/null &, потом убить его kill %1). Параллельно смотри vmstat 1, uptime и cat /proc/pressure/cpu - увидишь, как растут r, us и some в pressure.
- Запусти free -h, df -h и df -i. Убедись, что есть свободная память, место на диске и свободные inode.
Контрольные вопросы
- Назови пять подсистем, в одну из которых упирается любая проблема производительности.
- Чем утилизация отличается от насыщения? Какой из двух признаков честнее говорит о боли и какой современный механизм ядра меряет насыщение напрямую?
- В выводе vmstat колонка wa держится на 70, а b ненулевой. На какую подсистему это указывает и какой инструмент доставать дальше?
- Ты в облачной VM, внутри всё выглядит спокойно, но приложение лагает. Какую колонку vmstat/top проверить и о чём говорит её ненулевое значение?
- Почему опасно менять несколько настроек сразу, даже если "стало лучше"?
Диагностика - это метод, а не набор команд. Сначала сформулируй симптом конкретно, потом локализуй подсистему (CPU, память, диск, сеть, приложение), двигайся от общего к частному. Держи в голове USE: для каждого ресурса проверь утилизацию, насыщение и ошибки. Начинай с обзора (uptime, vmstat, free, df, dmesg) плюс PSI (/proc/pressure) для честного насыщения и читай вывод осмысленно - цифры должны разворачивать тебя в сторону одной подсистемы. И железная дисциплина: меняй по одной вещи и записывай, что делаешь. Всё остальное в курсе - strace, perf, eBPF/bpftrace - это инструменты, которые ты будешь доставать уже прицельно, зная, куда смотришь.