awesome-everything EN
↑ Обратно к восхождению

Производительность

Чтение флейм-графов: формы, профайлеры по языкам и 60-секундный скан

Суть Пять форм флейм-графа читаются за секунды до разбора названий. Правильный профайлер по языку даёт репрезентативные измерения.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 16 min

Сеньор открывает флейм-граф и говорит: «паттерн вулкана — фикс не в широком листе, а в слое диспетчеризации двумя уровнями выше». Он ещё не прочитал ни одного имени функции. Умение читать формы сокращает путь от профиля до гипотезы с минут до секунд.

Чтение флейм-графа за 60 секунд

Формат флейм-графов Брендана Грэгга — каноническое представление.

  • Ось Y: глубина стека вызовов. Точка входа (main, HTTP-хэндлер) внизу; листовая функция на CPU вверху.
  • Ось X: алфавитный порядок дочерних стеков. Позиция «левее/правее» ничего не говорит о порядке вызовов.
  • Ширина: пропорциональна количеству сэмплов = доле CPU-времени.

Рабочий процесс чтения:

  1. Сканируй верх графа на самые широкие листовые фреймы — это функции, находившиеся на CPU в момент сэмплирования.
  2. Спускайся вниз от широкого листа, чтобы увидеть, кто его вызвал, и один ли путь ведёт к нему в большинстве сэмплов или он раздроблен по многим вызывателям.
  3. Если большинство сэмплов сходятся к листу через один путь: это горячий путь; чини его.
  4. Если лист вызывается из многих родителей, каждый вносит тонкий вклад: чини сам лист, а не его вызывателей.

Самая частая ошибка новичка: читать горизонтальное положение как порядок времени. Это не так. Два соседних фрейма ничего не говорят о том, который выполнился раньше.

ОсьЗначениеЧастое неверное чтение
Ширина (x)Количество сэмплов — доля CPU-времениЧитают слева направо как «порядок времени» — это НЕ ТАК
Положение (x)Алфавитная группировка по родителюЛевый фрейм НЕ выполняется раньше правого
Высота (y)Глубина вызова — вход внизу, лист вверхуВысокий стек = глубокая вложенность, не медленнее

Пять форм флейм-графов и что они означают

Опытный глаз читает флейм-граф по форме за секунды, до того как увеличивает масштаб на имена.

1. Высокая узкая колонна, уходящая вверх по одному пути — рекурсия или глубокая цепочка middleware. Один фикс на листе или рядом с ним.

2. Широкое плато на одном уровне с десятками тонких листьев — диспетчер, раздающий работу многим хэндлерам. Фикс обычно в самом диспетчере или общем пути над ним, а не в каком-то одном хэндлере.

3. Две соседних широких колонны без общего родителя — два независимых горячих пути, требующих отдельных фиксов. Закон Амдала применяется к каждому независимо.

4. «Вулкан», расширяющийся от листа к корню — большой cum-time в одной точке входа с работой, распределённой ниже. Фикс зависит от того, на каком уровне реальная работа превращается в диспетчеризацию; иди по форме.

5. Тонкие шипы, рассыпанные по всей ширине — нет реального hotspot. Проблема задержки в другом месте (off-CPU, координация, сеть). CPU-профиль один не покажет её; попробуй off-CPU или allocation-профиль.

Это словарный запас, которым сеньоры описывают вид профиля до называния функций.

Выбор профайлера по языку

У каждого современного языка есть рекомендованный сэмплирующий профайлер. Правильный выбор избавляет от артефактов debug-сборки и ошибок обхода стека JVM.

  • Go: встроенный pprof через runtime/pprof и net/http/pprof — отраслевой стандарт. Читается go tool pprof, экспортирует pprof.proto.
  • Java: JFR (Java Flight Recorder, по умолчанию с JDK 11) и async-profiler — production-стандарт, так как правильно обходит Java-стеки через AsyncGetCallTrace, избегая safepoint bias.
  • Python: py-spy (внешний сэмплер, не требует изменений в приложении) и scalene. cProfile — инструментирующий, только для разработки, не для продакшена.
  • Node.js: встроенный --prof + clinic.js для флейм-графов; 0x для продакшена.
  • Rust: pprof-rs; perf с addr2line для разрешения символов.
  • Ruby: stackprof и rbspy.
  • PHP: tideways, Excimer.
  • C/C++: perf + perf-tools; Intel VTune для микроархитектурного анализа.

Бэкенды непрерывного профилирования (Pyroscope, Parca, Polar Signals, Datadog Continuous Profiler) принимают pprof или JFR от любого из них. eBPF-агенты захватывают стеки на стороне ядра и работают без учёта языка через DWARF-анврапинг для скомпилированных бинарей или JIT-эмитированных perf-мап для V8 и JVM.

Выбор сеньора: один основной профайлер на язык, один универсальный eBPF-baseline на всю инфраструктуру. Полиглот-команда должна нормализовать все профили в один бэкенд и читать их в одном инструменте.

Почему это работает

async-profiler для Java — канонический production-выбор в сравнении с JVMTI-профайлерами именно из-за AsyncGetCallTrace: он обходит Java-стеки в любой момент, а не только в safepoints. Safepoint-смещённые профайлеры переоценивают время методов, у которых есть safepoints в горячих циклах, и недооценивают время в нативных методах. Смещение может указывать на неверный hotspot в нагрузках с интенсивным GC.

Расставь шаги по порядку

Расставь по порядку 60-секундный рабочий процесс чтения флейм-графа:

  1. 1 Сканируй верхний край — найди самые широкие листовые фреймы (это функции на CPU)
  2. 2 Определи форму до чтения имён (высокая колонна? широкое плато? рассыпанные шипы?)
  3. 3 Спускайся вниз от самого широкого листа, чтобы увидеть, кто вызывал его чаще всего
  4. 4 Проверь, сходятся ли большинство сэмплов через один путь или веером из многих вызывателей
  5. 5 Если один путь: горячий путь там; если много вызывателей: фикс в самом листе
  6. 6 Читай имена функций и ищи их self-time vs cum-time в профиле
Викторина

Флейм-граф показывает тонкие шипы, рассыпанные по всей ширине, без доминирующего листового фрейма. Что это говорит о проблеме задержки?

Викторина

Почему async-profiler — предпочтительный production-профайлер для JVM-приложений, а не JVMTI-сэмплер?

Вспомните перед уходом
  1. 01
    Назови пять форм флейм-графов и что каждая из них предлагает в качестве фикса.
  2. 02
    Что такое safepoint bias в JVM-профайлерах и почему это важно для чтения флейм-графов?
Итог

Ось X флейм-графа — алфавитная группировка, а не время — самое частое неверное чтение. Ширина — количество сэмплов (доля CPU-времени); самый широкий лист — самая горячая функция. Читай форму до имён: высокая колонна означает рекурсию или фикс цепочки; широкое плато — фикс диспетчера; рассыпанные шипы — off-CPU проблема, не видимая в CPU-профиле. Выбор профайлера по языку — не эстетика: async-profiler избегает safepoint bias JVM; py-spy избегает GIL-интерференции Python; pprof — встроенный стандарт Go. Бэкенды непрерывного профилирования (Pyroscope, Parca) нормализуют все форматы в одно представление для всего полиглот-стека.

Связанные уроки
встречается в159
Продолжить восхождение ↑Статистические baseline''''ы: почему один запуск — не измерение
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.