perf: универсальный профайлер Linux

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

perf: универсальный профайлер Linux

Сообщение 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. Карта инструментов и сквозной разбор инцидента производительности
Ситуация знакомая: сервис тормозит, top показывает CPU под 100 процентов, а толку ноль. Ты видишь, ЧТО процесс жрёт ядро, но не видишь, ГДЕ внутри кода он это делает. В какой функции крутится цикл? Кто виноват - твой код, библиотека или само ядро? Вот тут strace бессилен (он про системные вызовы), а обычный мониторинг слишком крупнозернистый. Нужен инструмент, который заглянет внутрь работающей программы и скажет: "вот эта функция съела 40 процентов CPU". Этот инструмент - perf.

perf (он же perf_events) - штатный профайлер Linux, встроенный прямо в ядро. Это не сторонняя утилита, а интерфейс к аппаратным счётчикам процессора (PMU) и к точкам трассировки ядра. За это его называют швейцарским ножом производительности: один бинарник умеет считать инструкции CPU, ловить промахи кэша, строить профиль со стеками вызовов, анализировать планировщик и даже работать как strace. В этом уроке разберём perf linux по-человечески: с чего начать новичку и как читать вывод, а не просто запускать команды наугад. Актуально на 2026: perf по-прежнему базовый инструмент, но рядом с ним вырос зрелый стек eBPF (bpftrace, bcc), про связку с которым тоже скажем.

Как это устроено: сэмплирование против трассировки

Сначала про два режима, иначе дальше всё будет путаницей.

Счётчики (counting). Процессор имеет физические регистры PMU (Performance Monitoring Unit), которые молча тикают: "выполнено столько-то инструкций", "столько-то промахов кэша". perf просто читает эти числа до и после - почти без накладных расходов. Это режим perf stat.

Сэмплирование (sampling). perf периодически (например, 99 раз в секунду) прерывает программу и записывает, на какой инструкции и в какой функции она была в этот момент. Набрались тысячи замеров - получаем статистику: где код проводит время. Это perf record и perf top. Чем выше частота -F, тем точнее картина, но тем больше overhead.

Главное, что нужно усвоить новичку: perf НЕ замедляет программу в разы, как иногда думают про профайлеры. Накладные расходы низкие - единицы процентов, потому что считает аппаратура CPU, а не эмуляция. Поэтому perf можно запускать даже на боевом сервере, аккуратно и недолго.

Изображение

Установка и права (актуально на 2026)

perf живёт в пакете linux-tools, привязанном к версии ядра.

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

# Ubuntu/Debian
sudo apt install linux-tools-common linux-tools-$(uname -r)

# RHEL/Fedora/RED OS
sudo dnf install perf

# проверка
perf --version
На Astra Linux и RED OS пакет тоже называется perf и ставится из штатного репозитория. Если perf ругается "WARNING: perf not found for kernel" - значит версия пакета не совпала с ядром, доставь linux-tools именно под свой uname -r.

Про права важная деталь, которая часто стопорит новичков. Доступ к profiling регулирует sysctl kernel.perf_event_paranoid:
  • значение 2 (частый дефолт в дистрибутивах) - можно профилировать только свои процессы в user-space, ядро закрыто;
  • значение 1 - разрешает профилирование ядра пользователю с нужной capability;
  • значение -1 - почти всё разрешено (только для отладки, не на проде).
Проверить: cat /proc/sys/kernel/perf_event_paranoid. Раньше единственным выходом был sudo на всё подряд. На 2026 правильнее - capability CAP_PERFMON (появилась в ядре 5.8), которая даёт права на мониторинг без полного root по принципу наименьших привилегий:

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

sudo setcap cap_perfmon,cap_sys_ptrace,cap_bpf=ep $(command -v perf)
Тогда обычный пользователь сможет снимать профиль без sudo. В уроке для простоты оставим sudo, но в продакшене предпочитай CAP_PERFMON.

Первый perf stat: анализ крови для CPU

Начинаем с perf stat - это как анализ крови для CPU. Запусти любую команду под ним:

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

sudo perf stat ls /usr
Получишь блок вроде такого (обрезал):

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

      4,52 msec task-clock        #    0,891 CPUs utilized
         3      context-switches  #  663,7 /sec
         0      cpu-migrations    #    0,0  /sec
       110      page-faults       #   24,3 K/sec
 5 421 003      cycles            #    1,2 GHz
 6 510 870      instructions      #    1,20  insn per cycle
 1 320 110      branches          #  291,8 M/sec
    18 400      branch-misses     #    1,39% of all branches
Теперь самое важное - КАК это читать, поле за полем:
  • cycles и instructions - сколько тактов CPU и сколько инструкций отработало. Сами по себе цифры скучные, важна их связка.
  • insn per cycle (IPC) - сколько инструкций процессор выполняет за один такт. Это пульс программы. Хороший показатель для типичного кода - около 1.0 и выше (современный CPU умеет 2-4). Если IPC упал ниже 0.5 - процессор больше ждёт, чем работает: скорее всего стоит в ожидании памяти. Раньше выводили обратную метрику CPI (такты на инструкцию) - не путайся, это просто 1/IPC.
  • branch-misses - доля неверно предсказанных переходов (if, циклы). Норма - доли процента, до 1-2 процентов. Если 5-10 процентов - предсказатель переходов захлёбывается, код плохо предсказуем.
  • context-switches - сколько раз ОС переключала процесс. Много переключений (тысячи в секунду на один поток) - намёк на конкуренцию за блокировки или избыток потоков.
  • cpu-migrations - перекидывания потока между ядрами. Частые миграции бьют по кэшу, иногда лечатся привязкой к ядру (taskset/affinity).
Добавь -d, чтобы увидеть промахи кэша (можно и -dd, -ddd для большей детализации):

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

sudo perf stat -d ./my_program
В выводе появятся cache-references, cache-misses (с процентом), а также промахи L1 и LLC (последнего уровня кэша). Высокий процент cache-misses - программа гуляет по памяти хаотично, кэш не помогает. Это частая причина низкого IPC. Логика диагностики простая: маленький IPC -> смотрим cache-misses -> если они высокие, проблема в работе с памятью, а не в количестве вычислений. Полезные флаги: -r 5 повторит замер 5 раз и покажет разброс, а -p PID прицепится к уже работающему процессу.

perf record и perf report: где именно жжётся CPU

perf stat сказал "процессору плохо". Теперь надо понять, в каком коде. Тут выходит на сцену perf record - он сэмплирует стеки вызовов и пишет их в файл perf.data.

Профилируем живой процесс по PID 10 секунд, со стеками вызовов:

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

sudo perf record -F 99 -g -p 12345 -- sleep 10
Разбор флагов:
  • -F 99 - частота сэмплирования 99 Гц. Число намеренно нечётное, чтобы не попасть в резонанс с периодическими таймерами в системе и не получить смещённую картину.
  • -g - записывать call graph, то есть полный стек вызовов, а не только верхнюю функцию. Без -g увидишь "горит функция X", но не узнаешь, кто её вызвал.
  • -p 12345 - цепляемся к процессу. Можно вместо этого -a для всей системы или просто указать команду после --.
Про -g есть важный нюанс - способ размотки стека. По умолчанию стек разматывается по frame pointer (fp) - быстро, но на оптимизированных бинарниках без указателя кадра стеки получаются битыми. Способы:

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

sudo perf record -F 99 --call-graph dwarf -p 12345 -- sleep 10
  • --call-graph fp - по указателю кадра. Быстро, почти без overhead, но требует сборки с -fno-omit-frame-pointer, иначе стеки рвутся. Хорошая новость 2026: Ubuntu 24.04+ и Fedora уже пересобрали системные пакеты с frame pointer, так что fp снова стал рабочим по умолчанию на свежих дистрибутивах.
  • --call-graph dwarf - размотка по отладочной информации DWARF. Медленнее и тяжелее (perf копирует кусок стека на каждый сэмпл), зато стеки корректные даже на release-сборке без frame pointer. Не уверен в стеках - бери dwarf.
  • --call-graph lbr - аппаратный Last Branch Record на Intel Haswell и новее (и на свежих AMD Zen). Быстрый и точный, но ограничен глубиной (порядка 32 записей на старых, до сотен на новых CPU) и собирает в основном user-стек.
Теперь читаем профиль:

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

sudo perf report
Откроется интерактивный отчёт. Колонки:

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

# Children      Self  Command  Shared Object      Symbol
# ........  ........  .......  .................  ......................
    62,15%     0,08%  nginx    nginx              [.] ngx_http_process
    48,90%    31,20%  nginx    libc.so.6          [.] __memcpy_avx
    12,03%    12,03%  nginx    [kernel.kallsyms]  [k] copy_user_generic
Как это читать - ключевой момент урока:
  • Self - сколько CPU съела сама эта функция, без вложенных вызовов. Ищешь горячий код - смотри на Self.
  • Children - сколько съела функция вместе со всеми, кого она вызвала. Высокий Children при низком Self значит "сама функция дешёвая, но тянет за собой дорогих детей". У main почти всегда Children близок к 100 процентам - это нормально и ни о чём не говорит.
  • Shared Object - где живёт функция: твой бинарник, библиотека (libc.so.6) или ядро. Метка [.] - пользовательский код, [k] - код ядра.
  • Symbol - имя функции.
В примере выше видно: 31 процент Self ушло в __memcpy_avx - программа упёрлась в копирование памяти. Это и есть ответ на вопрос "куда смотреть дальше". В perf report нажми Enter на функции -> Annotate, чтобы увидеть, на каких именно ассемблерных инструкциях скапливаются сэмплы.

Если вместо имён функций ты видишь голые адреса вроде 0x00007f3a12, значит нет символов. Поставь debuginfo:

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

# RHEL/Fedora/RED OS
sudo dnf debuginfo-install nginx
# Debian/Ubuntu - пакеты с суффиксом -dbgsym (нужен репозиторий ddebs)
sudo apt install nginx-dbgsym
Свой код собирай с -g (отладочной информацией) - тогда символы появятся сами.

perf top, perf trace и братья по цеху

Иногда не хочется писать файл - хочется смотреть в реальном времени, что горит прямо сейчас. Для этого perf top, живой профайлер linux:

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

sudo perf top
Это как top, но по функциям, с обновлением на лету. Колонки те же: Overhead (доля CPU), Shared Object, Symbol. Самая прожорливая функция всегда вверху. Удобно, когда нагрузка плавает и нужно поймать всплеск глазами.

Чтобы узнать, какие вообще события умеет твой процессор и ядро:

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

perf list
Увидишь Hardware Events (cycles, instructions, cache-misses), Software Events (context-switches, page-faults) и сотни tracepoints ядра. Это меню того, что можно скормить в -e.

Отдельная фишка - perf trace. Работает почти как strace, показывает системные вызовы, но через perf_events, поэтому накладные расходы заметно ниже, чем у strace с его ptrace-ловушками:

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

sudo perf trace -p 12345
На проде, где strace может уронить производительность в разы, perf trace - более щадящий вариант.

Всё, что мы делали выше, - это on-CPU профилирование: ищем, где код жжёт процессор, пока реально работает. Но бывает обратная беда: IPC высокий, CPU не загружен, а сервис всё равно медленный - значит код спит в ожидании диска, сети или блокировки. Это off-CPU. У perf для этого есть perf sched:

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

sudo perf sched record -- sleep 5
sudo perf sched timehist
timehist покажет, какие потоки и как долго спали, а latency - суммарные задержки планировщика. Это уже мостик к eBPF: на 2026 для off-CPU анализа чаще берут offcputime из набора bcc или bpftrace - они дешевле и дают сразу стек ожидания.

perf и eBPF: кто кого в 2026

Зрелость eBPF поменяла расклад, и это надо понимать. perf никуда не делся - он лучший для on-CPU сэмплирования с аппаратными счётчиками и для построения флеймграфов. Но для трассировки конкретных событий (кто открывает файлы, какие запросы медленные, сколько живут TCP-сессии) сегодня удобнее bpftrace и bcc - они программируемые и фильтруют в ядре, отдавая наружу уже агрегат. Грубое правило: считать и сэмплировать CPU - perf; задавать точечные вопросы "кто и почему" - bpftrace. Свежие perf тоже умеют BPF под капотом (например off-CPU профилирование через --off-cpu в новых версиях), так что граница размывается.

perf record даёт сырые стеки. Чтобы превратить тысячи стеков в наглядную картинку, их сворачивают во флеймграф (flame graph) - это уже следующий шаг и следующий урок. Запомни связку: perf record собирает стеки -> из них рисуется флеймграф, где ширина прямоугольника равна доле CPU.

Типичные грабли
  • Запуск без прав. perf упирается в kernel.perf_event_paranoid. Проверь cat /proc/sys/kernel/perf_event_paranoid. Значение 2 закрывает ядро. Либо sudo, либо capability CAP_PERFMON через setcap, либо аккуратно sudo sysctl kernel.perf_event_paranoid=1.
  • Битые стеки. Видишь обрывки стека на одну строку - бинарник собран без frame pointer, а ты ловишь fp. Перезапиши с --call-graph dwarf.
  • Голые адреса вместо имён. Это не баг perf, это отсутствие debuginfo. Ставь -dbgsym / debuginfo-install или собирай свой код с -g.
  • Версия пакета не та. perf жёстко завязан на ядро. После обновления ядра доставь linux-tools-$(uname -r), иначе часть фич отвалится.
  • Профилируешь не то. Если IPC высокий, а сервис всё равно тормозит, проблема НЕ в CPU - процесс ждёт диск, сеть или блокировку. perf record про on-CPU; off-CPU ожидания ищи через perf sched или offcputime из bcc.
  • Слишком высокая -F на проде. -F 999 и выше заметно грузит систему и раздувает perf.data. Для боевого сервера 99 Гц на 10-30 секунд - безопасный режим.
Мини-лаба: повтори руками прямо сейчас
  • Поставь perf под своё ядро и проверь perf --version. Посмотри cat /proc/sys/kernel/perf_event_paranoid.
  • Запусти sudo perf stat -d -- find / -name "*.conf" 2>/dev/null. Найди в выводе IPC и процент cache-misses, оцени их по правилам из урока.
  • Создай нагрузку: yes > /dev/null & и запомни его PID.
  • Сними профиль: sudo perf record -F 99 -g -p PID -- sleep 5, затем sudo perf report. Найди функцию с максимальным Self, нажми на ней Annotate.
  • Запусти sudo perf top на 10 секунд и поймай вершину списка. Не забудь kill PID после.
Контрольные вопросы
  • Чем сэмплирование (perf record) отличается от подсчёта счётчиков (perf stat) и когда что применять?
  • Что показывает IPC и какое значение должно тебя насторожить? Куда смотреть дальше, если IPC низкий?
  • В чём разница между колонками Self и Children в perf report и почему у main всегда большой Children?
  • Почему вместо имён функций иногда видны голые адреса и как это лечится? Чем отличаются --call-graph fp и --call-graph dwarf?
Что запомнить

perf - штатный профайлер с низким overhead, можно аккуратно крутить даже на проде. Начинай с perf stat (здоровье CPU: IPC, cache-misses, branch-misses), затем perf record -g + perf report, чтобы найти горячую функцию по Self. perf top - тот же профиль в реальном времени, perf trace - лёгкая замена strace, а perf sched - вход в off-CPU. Для читаемых имён нужны символы и debuginfo, для корректных стеков на release-сборках - --call-graph dwarf. В 2026 perf делит сцену с eBPF: считать и сэмплировать - perf, точечные вопросы - bpftrace/bcc. А собранные стеки - прямой путь к флеймграфам, которые разберём дальше.
👍4 ❤️3 🔥1 😄 🤔2
Аватара пользователя
ArchAndy
Сообщения: 1
Зарегистрирован: 27 май 2026, 01:45

Re: perf: универсальный профайлер Linux

Сообщение ArchAndy »

Спасибо, наконец дошло про Self и Children. Раньше смотрел в perf report и не понимал, почему у main 90% а делать с этим нечего. Теперь ясно - надо по Self искать, а большой Children у main это норма.
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
proxmoxcoder
Сообщения: 1
Зарегистрирован: 11 май 2026, 15:01

Re: perf: универсальный профайлер Linux

Сообщение proxmoxcoder »

Про CAP_PERFMON прям спасибо, замучился везде sudo тыкать. Сделал setcap на perf и снимаю профиль из-под обычного юзера, красота. И про off-CPU через perf sched раньше вообще не знал, думал perf только про CPU.
👍1 ❤️1 🔥1 😄 🤔1
Ответить
← Предыдущая глава
Накладные расходы трассировки и безопасные альтернативы
Следующая глава →
Флеймграфы: визуализация профиля производительности

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

Поделиться темой: ✈ Telegram VK
Похожие запросы: как посмотреть сколько памяти занято в linuxlsof кто держит файл и порт в linuxperf top как найти что грузит процессорчто такое системный вызов и зачем трассироватьhtop и top как читать и в чем разницаoom killer кто убил процесс linux как узнать

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

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

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