Источники правды: load average, /proc и /sys

Рейтинг: 45.3% · 9 голосов
Подробный курс по диагностике и производительности 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

Источники правды: load average, /proc и /sys

Сообщение 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. Карта инструментов и сквозной разбор инцидента производительности
Тебе звонят в три ночи: "сервер лежит, load average 542, всё пропало". Ты заходишь по ssh, а top показывает 30% простоя CPU и кучу свободной памяти. Парадокс? Нет. Просто почти никто не знает, что такое load average на самом деле, и из этого недопонимания рождается половина ночных паник. В этом уроке разберём, откуда система вообще берёт цифры, развеем главный миф про загрузку, докопаемся до истории и арифметики этих трёх чисел, научимся доставать любую метрику руками - даже когда привычной утилиты под рукой нет - и подключим современный источник правды, который многие до сих пор игнорируют: PSI (pressure stall information).

Что такое load average linux и почему 542 - это не приговор

Давай сразу про миф. Многие думают, что load average - это "загрузка процессора в процентах". Это неправда. Load average в Linux - это среднее число процессов (точнее, потоков, в ядре их называют scheduling entities), которые в данный момент чего-то хотят: либо крутятся на CPU, либо стоят в очереди за CPU, либо ждут диск в особом состоянии.

Формально в счётчик попадают два типа задач:
  • Runnable (R, в ядре TASK_RUNNING) - готовы выполняться: либо уже на ядре, либо в очереди ждут своей доли CPU.
  • Uninterruptible sleep (D, в ядре TASK_UNINTERRUPTIBLE) - "непрерываемый сон". Задача застряла в ожидании ресурса, обычно дискового ввода-вывода (или сетевой ФС вроде NFS), а иногда это ожидание ядерной блокировки (мьютекса, семафора). Её даже сигналом не разбудишь, пока ресурс не ответит. Сигнал kill -9 такую задачу не снимет - она невидима для сигналов до возврата из ядра.
Вот это второе - чисто линуксовая особенность. В большинстве других Unix (классический BSD, Solaris и так далее) load average считает только очередь к процессору, то есть чистый спрос на CPU. Linux же исторически добавил туда задачи в состоянии D. Поэтому твой load может взлететь до 542 не от нехватки CPU, а от того, что сетевая шара отвалилась и три сотни процессов висят в D, ожидая ответа NFS. CPU при этом скучает.

Запомни главную аналогию. Load average - это не спидометр (как быстро едем), а число людей в очереди к кассе плюс те, кто уже у кассы. Очередь из 542 человек к одной кассе - катастрофа. Та же очередь к 256 кассам - норма.

Отсюда железное правило чтения load average linux: всегда дели на число ядер. Узнаём число ядер:

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

nproc
# или подробнее (логические CPU, ядра, сокеты):
lscpu | grep -E '^CPU\(s\):|Core|Socket|Thread'
Если nproc выдал 8, а load average равен 8.0 - система загружена ровно "под завязку", очередь равна числу касс, всё впритык, но без затыка. Load 4.0 на 8 ядрах - наполовину свободна. Load 16.0 на 8 ядрах - вдвое больше работы, чем железо тянет, процессы реально ждут. Так что "542" само по себе не значит ничего, пока ты не знаешь, сколько ядер и из чего этот load набрался. И сразу важная оговорка на 2026: load average плохо отличает "не хватает CPU" от "не хватает диска". Деление на число ядер - правильная привычка, но из-за примеси D-state даже "load на ядро" - грубая оценка, а не точный диагноз. Именно поэтому ниже мы разберём PSI - он показывает не количество ждущих, а именно потерянное на ожидании время, и разделяет CPU, память и io по отдельности.

Изображение

Главная тайна load average: почему в Linux он "лукавый" (разбор статьи Брендана Грегга)

Есть классическая статья Брендана Грегга "Linux Load Averages: Solving the Mystery" (2017, перевод на Хабре от VK). Она разбирает ровно то заблуждение, с которого мы начали, и доводит его до самого корня - до строчек ядра и до письма 1993 года. Перескажу суть, потому что без неё load average так и останется магическим числом.

История: патч 1993 года. В ранних Unix и в самом раннем Linux load average был честным "спросом на CPU" - считал только задачи в TASK_RUNNING. Но 29 октября 1993 года инженер Matthias Urlichs прислал крошечный патч (вошёл в Linux 0.99.14, ноябрь 1993; в 0.99.13 его ещё не было), который добавил в учёт задачи в состоянии TASK_UNINTERRUPTIBLE. Его обоснование (в переводе с оригинала письма) звучало так:
Проблема в том, что процессы, которые свопятся или ждут "быстрый", то есть непрерываемый, ввод-вывод, тоже потребляют ресурсы. Выглядит контринтуитивно, что load average падает, когда ты меняешь быстрый диск под своп на медленный.
Логика простая и сильная: если поставить диск медленнее, система станет хуже, а старый load average при этом уменьшался (процессы дольше спят в ожидании io, а спящих он не считал). Это абсурд. Urlichs хотел, чтобы число отражало "спрос на систему в целом" с точки зрения человека, а не только очередь к процессору. Спустя 24 года, когда Грегг его об этом спросил, он сформулировал то же самое ещё яснее: смысл load average - дать число, показывающее, насколько система занята с человеческой точки зрения; машина, заваленная дисковым io, может быть жутко тормозной, но иметь TASK_RUNNING-нагрузку всего 0.1 - и такое число никому не поможет.

Вот почему в Linux load average - это не "спрос на CPU", а "спрос на систему" (system load): runnable плюс uninterruptible. Это сознательное проектное решение 1993 года, а не баг. И отсюда же растёт его двусмысленность: по одному LA ты не отличишь CPU-затык от io-затыка. Высокий load в Linux честно означает "системе тяжело", но не говорит, почему тяжело.

Из чего реально складывается число. Грегг не поверил на слово и измерил вклады в load с помощью off-CPU flame graphs (инструмент offcputime из bcc/eBPF с фильтром по состоянию TASK_UNINTERRUPTIBLE). На 8-ядерной машине во время распаковки tar он разложил load average 1.19 буквально по слагаемым:
  • 0.33 - время tar на CPU (это и есть "честный" CPU-спрос);
  • 0.67 - tar в непрерываемом сне на чтении с диска (тот самый D-state);
  • 0.04 - прочие потребители CPU в ядре;
  • 0.11 - ядерные воркеры в непрерываемом io.
Сложи - получишь те самые 1.19. То есть больше половины "нагрузки" здесь - это вовсе не CPU, а ожидание диска. Кроме диска, в D-state (а значит, и в load) попадает и ожидание блокировок: Грегг ловил, например, конкуренцию за rw-семафор в ядре (стек rwsem_down_read_failed). Поэтому строгая, но честная формулировка: load average - это экспоненциально затухающее среднее числа задач в TASK_RUNNING плюс TASK_UNINTERRUPTIBLE.

Три числа 1/5/15 - это не "среднее за минуту", а экспоненциальное затухание

Второй большой инсайт из той же статьи: три числа в loadavg - это не простое среднее арифметическое за 1, 5 и 15 минут. Это экспоненциально затухающие скользящие средние (exponentially-damped moving averages). Ядро раз в 5 секунд берёт текущее число активных задач и подмешивает его в накопленное значение по формуле затухания:

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

новое = старое * EXP + текущее * (1 - EXP)
где EXP - константа затухания, своя для каждого окна. В ядре они зашиты как fixed-point числа:

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

#define EXP_1   1884   /* 1/exp(5sec/1min)  */
#define EXP_5   2014   /* 1/exp(5sec/5min)  */
#define EXP_15  2037   /* 1/exp(5sec/15min) */
Это та самая функция calc_load() в планировщике. Сами константы тянутся аж из системы TENEX 1970-х - арифметику load average просто перенесли в Linux как есть. Чем больше окно (15 минут), тем ближе EXP к единице, тем "тяжелее" и инерционнее число: старое значение почти не размывается новыми замерами.

Практическое следствие, которое многих удивляет: если на простаивающей системе запустить ровно один CPU-bound поток и подождать ровно 60 секунд, одноминутный load average покажет не 1.0, а примерно 0.62. Он ещё не успел "догнать" реальную нагрузку - экспонента подходит к цели асимптотически. Поэтому одноминутное число реагирует быстро, но дёргано; пятнадцатиминутное - медленно и плавно. Это не среднее за прошедшую минуту, а "взвешенная память" системы с разной длиной.

Зато это даёт бесплатный тренд без всякого мониторинга. Как читать три числа вместе:
  • 1-минутное сильно больше 15-минутного (например 12.0 / 3.0 / 1.5) - нагрузка растёт прямо сейчас, проблема свежая, реагируй немедленно.
  • 1-минутное меньше (1.5 / 4.0 / 9.0) - пик уже прошёл, система выдыхает, возможно ты опоздал на разбор и ловишь хвост.
  • Все три близки - стабильный установившийся режим, нагрузка ровная.
Как правильно пользоваться load average (и где остановиться). Подытожим Грегга по-инженерному:
  • LA - это грубый индикатор тренда: "стало ли системе хуже, чем было час назад". Для этого он отличный и дешёвый (одно чтение файла).
  • Дели на число ядер, чтобы прикинуть масштаб, но помни про примесь D-state: "load на ядро = 2" может быть и реальной CPU-перегрузкой вдвое, и сотней процессов, висящих на отвалившемся NFS при пустом процессоре.
  • Абсолютный порог сам по себе бессмысленен: load 25 на 2 ядрах и на 64 ядрах - совершенно разные ситуации, а ещё надо знать, из чего этот load набрался.
  • Для точной диагностики LA принципиально недостаточно - он смешивает CPU, диск и блокировки в одно число и по определению не может их разделить. Дальше нужны прицельные метрики: mpstat -P ALL 1 (загрузка по ядрам), pidstat 1 (по процессам), vmstat 1 (колонка r - длина runqueue), iostat -x 1 (диски) и - главное на 2026 - PSI, к которому мы и идём.
В ядре, кстати, над функцией расчёта load висит знаменитый комментарий в духе "это дурацкое число, но люди считают его важным". Воспринимай его именно так: полезный сигнал тревоги и тренда, но не диагноз.

proc linux: где система прячет настоящие linux метрики

Теперь к самому важному вопросу урока: откуда берутся цифры? Ответ - из псевдофайловой системы /proc. Это не файлы на диске. Это окно прямо в ядро: каждый "файл" в /proc ядро рисует на лету в момент, когда ты его читаешь. Открыл - получил свежий снимок состояния. Поэтому у многих из них размер 0, а mtime бессмысленна.

Ключевая мысль урока: почти все привычные утилиты (top, uptime, free, ps, vmstat) - это просто красивые обёртки над /proc. Они читают те же текстовые файлы, что доступны и тебе. Значит, если top не установлен (а на голом контейнере или урезанном образе так и бывает), метрику всё равно можно достать голыми руками.

Сам load average лежит здесь:

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

cat /proc/loadavg
0.52 0.43 0.38 2/431 18922
Читаем по полям слева направо:
  • 0.52 0.43 0.38 - те самые средние за 1, 5 и 15 минут (число задач в очереди R плюс задачи в D), посчитанные экспоненциальным затуханием, как разобрали выше.
  • 2/431 - до слэша число runnable прямо сейчас (готовы бежать), после слэша - сколько всего scheduling entities существует в системе.
  • 18922 - PID, который был создан последним. По нему, кстати, видно, как бурно система плодит процессы.
Дальше - сердце CPU-статистики, /proc/stat:

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

cat /proc/stat
cpu  259812 1043 88234 9881233 12044 0 3120 0 0 0
cpu0 64903   210  22011 2470308 3011  0  812  0 0 0
...
ctxt 884512033
procs_running 2
procs_blocked 1
Строка cpu - суммарное время по всем ядрам в тиках (USER_HZ, обычно 1/100 секунды). Колонки строго по порядку: user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. Что важно новичку:
  • idle (4-я цифра) - простой. Большая - хорошо, CPU свободен.
  • iowait (5-я) - сколько ядро как бы "ждало диск". Растёт - подозревай диск. Но осторожно: iowait в Linux лукавит, на многоядерных он занижен и приблизителен, опираться только на него нельзя. На 2026 правильнее смотреть io-давление через PSI, см. ниже.
  • steal (8-я) - на виртуалке это время, которое гипервизор отобрал в пользу соседей. Большой steal на VPS - тебя "обкрадывает" сосед по гипервизору или ты упёрся в лимит тарифа.
Это монотонные счётчики, которые только растут. Чтобы получить проценты, утилиты делают два замера с паузой и считают разницу - ровно это под капотом у top и mpstat. Внизу сразу видно procs_running (готовы бежать) и procs_blocked (застряли в D на вводе-выводе) - вот они, кирпичики load average, без всяких утилит. Поле ctxt - суммарное число переключений контекста с момента загрузки.

Память живёт в /proc/meminfo:

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

grep -E 'MemTotal|MemFree|MemAvailable|Dirty|Writeback' /proc/meminfo
MemTotal:       16307840 kB
MemFree:         1204736 kB
MemAvailable:    9214208 kB
Dirty:              1280 kB
Writeback:             0 kB
Новичку: смотри на MemAvailable, а не на MemFree. Available - честная оценка ядра, сколько реально можно отдать новым программам без свопа, с учётом кэшей, которые ядро отдаст по требованию. Поэтому "мало MemFree" почти всегда ложная тревога - free съеден под кэш страниц и легко освобождается. Dirty - данные, ещё не сброшенные на диск; если эта цифра огромная и не падает, ищи затык в io.

PSI: современный честный источник правды про насыщение (актуально на 2026)

Load average отвечает на вопрос "сколько задач ждёт", но не на вопрос "насколько мне от этого больно и из-за чего". Мы только что видели, в чём его слабость: историческая, лукавая метрика, которая сваливает CPU, диск и блокировки в одно затухающее число. PSI - его прямая противоположность: современная, честная метрика насыщения. Это и есть центральная пара урока - LA против PSI.

PSI - pressure stall information появился в ядре 4.20 (конец 2018). Идея в одном предложении: вместо того чтобы считать, сколько задач в очереди, ядро напрямую измеряет время, которое задачи реально простояли в ожидании ресурса. Не "542 человека в очереди", а "за последнюю минуту 15% времени кто-то стоял и ничего не делал, потому что ждал диск". Это прямое измерение потерь, а не косвенный прокси. На 2026 PSI включён по умолчанию практически везде: современные ядра, systemd, cgroup v2 (он теперь дефолтная иерархия в RHEL 9+/Astra/RED OS) - всё опирается на PSI. Это первое, куда я смотрю вместо гадания по iowait.

Три файла:

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

cat /proc/pressure/cpu
some avg10=0.00 avg60=2.31 avg300=1.07 total=98231456

cat /proc/pressure/memory
some avg10=0.00 avg60=0.00 avg300=0.05 total=412233
full avg10=0.00 avg60=0.00 avg300=0.02 total=205110

cat /proc/pressure/io
some avg10=15.40 avg60=9.22 avg300=4.10 total=512904881
full avg10=12.01 avg60=7.88 avg300=3.55 total=498120033
Разбор полей. avg10/avg60/avg300 - это процент времени за последние 10/60/300 секунд, в течение которого работа стояла из-за нехватки ресурса. total - суммарное абсолютное время простоя в микросекундах с момента загрузки (монотонный счётчик; именно его удобно класть на графики, считая дельты, - точно как со счётчиками из /proc/stat). Три окна 10/60/300 дают тот же приём чтения тренда, что и 1/5/15 у load average: avg10 растёт, а avg300 ещё низкий - давление только началось.

some против full - физический смысл. Это ключ ко всему PSI:
  • some - доля времени, когда хотя бы одна задача стояла в ожидании ресурса (а другие, может, работали). Это индикатор "ресурс под давлением, кому-то уже мешает".
  • full - доля времени, когда все незаблокированные иначе задачи стояли одновременно, то есть никто не мог работать, потому что всё уперлось в ресурс. Это чистая, уже состоявшаяся потеря производительности и пропускной способности (для памяти - классический симптом thrashing, когда система только и делает, что свопит/перечитывает страницы).
Историческая тонкость: для cpu строки full на уровне всей системы исторически не было (если кто-то ждёт CPU, значит CPU кем-то занят, и "все стоят" на уровне машины бессмысленно). С ядра 5.13 строка full для cpu появилась, но на системном уровне она во многом для совместимости; практически по cpu смотри some. А вот для memory и io именно full - самый ценный сигнал реальной боли.

Чем PSI честнее load average. Сравни напрямую. LA говорит "в среднем 16 задач чего-то хотят" - но не говорит, чего и насколько это вредит. PSI говорит "io full avg60 = 12" - это буквально "12% последней минуты вся полезная работа стояла колом из-за диска". Первое - косвенная оценка спроса, замешанная экспонентой; второе - прямое измерение насыщения и потерянного времени, отдельно по каждому ресурсу. Поэтому PSI разом снимает обе болезни load average: он разделяет CPU/память/io (LA их смешивает) и измеряет боль, а не очередь. Грубое правило: io some/full устойчиво выше 10-20% - диск ваше бутылочное горло, и это намного надёжнее, чем iowait из /proc/stat.

PSI по cgroup v2 - давление на конкретный сервис/контейнер. Системный /proc/pressure говорит про машину в целом. Но в мире контейнеров и systemd-юнитов важнее, кто именно давит. В cgroup v2 те же три файла лежат внутри каждой группы в cgroupfs:

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

# давление по памяти на конкретный systemd-сервис:
cat /sys/fs/cgroup/system.slice/nginx.service/memory.pressure
some avg10=0.00 avg60=1.20 avg300=0.40 total=88120
full avg10=0.00 avg60=0.95 avg300=0.31 total=61003

# io-давление внутри контейнера (docker/containerd кладут группы сюда):
cat /sys/fs/cgroup/system.slice/docker-<id>.scope/io.pressure

# а вот так быстро найти, какой сервис сейчас сильнее всех давит по io:
grep -r '' /sys/fs/cgroup/*/*/io.pressure 2>/dev/null | grep full
Это меняет диагностику качественно: вместо "машине плохо по io" ты получаешь "по io давит именно postgresql.service, остальные группы чистые". Один сервис может прижать диск так, что страдают все, - PSI по cgroup показывает виновника адресно, а не усреднённо по железу.

PSI для алертов и для systemd-oomd. Два практических применения:
  • Алерты. У PSI есть механизм триггеров: процесс из userspace открывает файл pressure, пишет в него порог в формате "some|full <простой_в_мкс> <окно_в_мкс>" и засыпает на poll()/epoll(); ядро будит его ровно тогда, когда давление пробивает порог. Это честный event-driven алерт ("за 1 секунду окна 200 мс простояли на памяти") вместо опроса load average по таймеру. На графиках/в Prometheus берут avg60 или дельты total.
  • systemd-oomd. Это пользовательский OOM-демон, который как раз живёт на PSI. Он следит за memory.pressure по cgroup и, если давление по памяти держится выше порога (ManagedOOMMemoryPressureLimit, скажем 60%) дольше заданного времени (DefaultMemoryPressureDurationSec, обычно порядка 20-30 секунд), заранее убивает самый прожорливый cgroup - не дожидаясь, пока в дело вступит ядерный OOM-killer по факту полного исчерпания памяти. Реакция на боль (давление), а не на катастрофу (память кончилась) - в этом вся разница и весь смысл PSI.
Итог пары: load average - историческая, удобная, но лукавая метрика спроса (runnable + D, экспонента, не делит ресурсы). PSI - современная честная метрика насыщения (прямое время простоя, some/full, отдельно по cpu/memory/io, по cgroup, с триггерами). На 2026 правильный рефлекс такой: LA - чтобы заметить, что стало хуже; PSI - чтобы понять, чего именно не хватает и кому.

Заглядываем внутрь процесса: /proc/PID и устройства в /sys

Каждый процесс - это каталог /proc/<PID>/. Возьмём PID 1410:

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

cat /proc/1410/status | grep -E 'State|VmRSS|Threads'
State:   D (disk sleep)
VmRSS:   204812 kB
Threads: 8
State: D - тот самый непрерываемый сон, кирпичик из которого складывается "лукавая" часть load average. Если видишь кучу процессов в D - вот источник раздутого load при простаивающем CPU. VmRSS - реально занятая физическая память процесса (резидентная). Полезные подкаталоги:
  • /proc/PID/fd/ - открытые файловые дескрипторы (ls -l покажет, на какие файлы и сокеты они смотрят; так ловят "кто держит удалённый файл" - удалённый, но открытый файл виден как (deleted), и место не освобождается).
  • /proc/PID/smaps / smaps_rollup - детальная карта памяти по сегментам, для разбора утечек и подсчёта PSS (честная доля общей памяти).
  • /proc/PID/stack - где в ядре застрял зависший процесс (нужен root). Бесценно, чтобы понять, в каком именно вызове висит задача в состоянии D - ровно тем же приёмом (стеки задач в D) Грегг разбирал, из чего набирается load average.
Если процесс намертво в D, первым делом смотри стек ядра:

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

sudo cat /proc/1410/stack
А вот /proc - про процессы и общесистемное, тогда как /sys (sysfs) - про железо и настройки ядра: устройства, диски, сетевые карты, тюнинг. Пара рабочих примеров:

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

# планировщик ввода-вывода для диска sda:
cat /sys/block/sda/queue/scheduler
[mq-deadline] kyber bfq none

# вращающийся диск или SSD (1 = HDD, 0 = SSD/NVMe):
cat /sys/block/sda/queue/rotational
В современных ядрах по умолчанию работает blk-mq, и в скобках виден активный планировщик (тут mq-deadline). Через /sys параметры не только читаются, но и меняются на лету (с sudo), но это уже тема уроков по тюнингу. Сейчас важно: /proc - источник правды по нагрузке и процессам, /sys - по устройствам и параметрам ядра. Кстати, PSI по cgroup (memory.pressure и компания) лежит именно под /sys/fs/cgroup - формально это тоже sysfs-ветка, смонтированная как cgroup v2.

Типичные грабли и заблуждения
  • "Load average - это проценты CPU." Нет. Это число задач в очереди плюс застрявшие в D, причём посчитанное экспоненциальным затуханием. Может расти при простаивающем процессоре.
  • "Это среднее за последнюю минуту." Нет, это экспоненциально затухающее среднее с константой 1 минута. После 60 секунд ровно одной нагрузки одноминутное число будет около 0.62, а не 1.0.
  • "Load 1.0 - это плохо." Само по себе - бессмысленно. 1.0 на одном ядре = впритык, на 64 ядрах = почти спит. Всегда дели на nproc (помня про примесь D-state).
  • "Мало MemFree - надо срочно добавлять память." Смотри MemAvailable. Linux намеренно набивает свободную RAM кэшем, это правильно, а не утечка.
  • "Высокий load - виноват CPU." Проверь procs_blocked, State: D в /proc/PID/status и /proc/pressure/io. Часто виноват диск, блокировка или зависшая сетевая шара, а не процессор.
  • "iowait высокий - точно диск умирает." iowait приблизителен и на многоядерных занижен. На 2026 доверяй PSI (io some/full), а не голому iowait.
  • "PSI some и full - про одно и то же." Нет: some - кому-то уже мешает; full - не может работать никто (для памяти/io это и есть настоящая боль).
  • "/proc - это обычные файлы." Это интерфейс к ядру. Размер у многих 0, mtime бессмысленна, содержимое генерится в момент чтения.
Мини-лаба: достань метрики руками

Десять минут практики, всё без установки чего-либо:
  • Узнай число ядер: nproc. Запиши.
  • Прочитай cat /proc/loadavg. Раздели первое число на nproc - какая доля нагрузки?
  • Создай CPU-нагрузку: yes > /dev/null & (запусти столько раз, сколько у тебя ядер), подожди минуту, снова глянь loadavg - оно подползло к nproc, но за 60 секунд не дотянет ровно (экспонента!). Заодно глянь cat /proc/pressure/cpu - some должно вырасти. Потом убей: kill %1 %2 %3 (или jobs, потом kill по номерам).
  • Найди процессы в непрерываемом сне:

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

    ps -eo pid,stat,comm | awk '$2 ~ /D/'
  • Посмотри живые счётчики планировщика: grep procs /proc/stat - сравни procs_running и procs_blocked.
  • Сравни источники io-давления: запусти dd if=/dev/zero of=/tmp/t bs=1M count=4000 oflag=direct и параллельно смотри cat /proc/pressure/io - как растёт io some, а на full проявляется реальный затык. Сравни с iowait из /proc/stat - почувствуй, насколько PSI нагляднее.
  • Для бонуса: найди cgroup своего шелла и глянь его давление - cat /proc/self/cgroup, затем cat /sys/fs/cgroup/<путь>/io.pressure.
Контрольные вопросы:
  • Из каких двух состояний процессов складывается load average в Linux и какое из них добавили патчем 1993 года?
  • Почему после 60 секунд ровно одной CPU-нагрузки одноминутный load average показывает ~0.62, а не 1.0?
  • load average показывает 16.0. Это много или нормально? Какой одной командой ты это определишь и почему ответ всё равно будет неполным?
  • Какой файл - первоисточник для top, uptime и free, и почему его можно читать напрямую?
  • У процесса State: D в /proc/PID/status. На что это намекает и куда смотреть дальше (хотя бы два места)?
  • Чем отличаются some и full в /proc/pressure/io и почему PSI честнее показывает узкое место, чем iowait и чем load average?
Что запомнить

Load average - это очередь задач (runnable + uninterruptible D), а не проценты CPU; это сознательное решение Matthias Urlichs от 1993 года ("спрос на систему", а не только на CPU), и считается оно экспоненциальным затуханием с окнами 1/5/15 минут, а не простым средним. Читать его надо всегда делёным на число ядер и понимая, что по одному LA не отличить CPU-затык от io-затыка. Все привычные утилиты - обёртки над /proc, и любую метрику можно достать голыми руками: /proc/loadavg, /proc/stat, /proc/meminfo, /proc/PID/. Железо и настройки ядра - в /sys. А чтобы не гадать "это CPU, память или диск и кто виноват" - на 2026 есть PSI в /proc/pressure/ и в cgroup v2: он прямо измеряет процент потерянного на ожидании времени (some/full, avg10/60/300, total) по каждому ресурсу и по каждому сервису, питает алерты и systemd-oomd. Связка простая: LA - заметить, что стало хуже; PSI - понять, чего именно не хватает и кому. Когда привычной тулзы нет, ты теперь не беспомощен: знаешь, где у системы лежит правда. (На Astra Linux и RED OS всё это работает один в один - ядро то же самое, cgroup v2 и PSI на месте.)
👍4 ❤️1 🔥2 😄 🤔2
Аватара пользователя
rray01
Сообщения: 1
Зарегистрирован: 22 май 2026, 01:33

Re: Источники правды: load average, /proc и /sys

Сообщение rray01 »

Спасибо, наконец-то дошло почему у меня load 40 был при пустом проце - там как раз nfs отваливался и куча процессов в D висела. Раньше думал что проц горит. А про /proc/pressure/io вообще не знал, проверил на проде - io full 18%, теперь понятно куда диск утекает.
👍1 ❤️1 🔥 😄 🤔
Аватара пользователя
kotlin2
Сообщения: 2
Зарегистрирован: 25 май 2026, 02:32

Re: Источники правды: load average, /proc и /sys

Сообщение kotlin2 »

А подскажите, procs_blocked в /proc/stat и количество процессов в D через ps - это всегда одно и то же число должно быть или могут расходиться? И PSI some по io лучше смотреть чем iowait, я правильно понял?
👍1 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Где лежат логи Linux: /var/log, dmesg и rsyslog
Следующая глава →
Процессы Linux: ps, pstree и состояния процессов

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

Поделиться темой: ✈ Telegram VK

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

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

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