Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Flamegraph: анализ производительности

Flamegraph на практике: чтение и анализ профилей производительности

Как читать flamegraph: ширина кадров, стеки вызовов, поиск узких мест CPU и памяти, инструменты генерации и практические паттерны оптимизации по профилям.

Прямой ответ

Flamegraph — визуализация стеков вызовов для анализа производительности (flamegraph — «стек вызовов как пламя» — flamegraph — метрики — «где тратится CPU/память» — flamegraph), зачем: найти узкое место в коде (flamegraph — «какая функция жрёт CPU» — flamegraph — метрики — «не гадать, а видеть» — flamegraph — linux — «визуально — быстрее» — flamegraph); как читать (flamegraph — «оси» — flamegraph): (1) Ось X (flamegraph — «ширина = время/сэмплы» — flamegraph — метрики — «шире = больше времени» — flamegraph — «широкий кадр = узкое место» — flamegraph — «не высота, а ширина» — flamegraph); (2) Ось Y (flamegraph — «глубина стека» — flamegraph — метрики — «выше = глубже вызов» — flamegraph — «стек вызовов снизу вверх» — flamegraph); (3) Цвет (flamegraph — «обычно не несёт смысла» — flamegraph — метрики — «цвет — для различения» — flamegraph — «не интерпретировать цвет» — flamegraph); главное правило (flamegraph — «ширина = время» — flamegraph — метрики — «ищи широкие кадры» — flamegraph — «широкий = много времени» — flamegraph — «плато (plateau) — где время тратится» — flamegraph — linux); типы flamegraph (flamegraph): (1) CPU flamegraph (flamegraph — «где тратится CPU» — flamegraph — метрики — «on-CPU время» — flamegraph — perf/pprof (pprof — «CPU профиль» — pprof); (2) Memory/heap flamegraph (flamegraph — «где allocating память» — flamegraph — метрики — «heap профиль» — flamegraph — утечки — «утечки памяти» — flamegraph); (3) Off-CPU flamegraph (flamegraph — «где ждёт (IO/lock)» — flamegraph — метрики — «off-CPU время» — flamegraph — «блокировки/IO» — flamegraph); (4) Differential flamegraph (flamegraph — «разница до/после» — flamegraph — метрики — «что изменилось» — flamegraph — «регресс/улучшение» — flamegraph); инструменты (flamegraph): (1) perf + FlameGraph (flamegraph — Linux perf (flamegraph — «perf record → flamegraph» — flamegraph — linux — Brendan Gregg (flamegraph — «FlameGraph» — flamegraph); (2) py-spy (flamegraph — Python (flamegraph — «py-spy — flamegraph Python» — flamegraph — python — «без изменения кода» — flamegraph); (3) pprof (pprof — Go (pprof — «pprof — flamegraph Go» — pprof — flamegraph — «go tool pprof» — pprof); (4) Pyroscope (continuous profiling — continuous profiling (continuous profiling — «flamegraph в проде» — continuous profiling — flamegraph — «непрерывные профили» — continuous profiling); когда flamegraph: сервис тормозит (flamegraph — «где узкое место» — flamegraph — метрики — «CPU/память» — flamegraph), оптимизация (flamegraph — «что оптимизировать» — flamegraph — метрики — «широкие кадры» — flamegraph), регресс (flamegraph — «что изменилось» — flamegraph — метрики — differential (flamegraph — «до/после» — flamegraph); антипаттерны: интерпретировать высоту (flamegraph — «высота ≠ время» — flamegraph — метрики — «ширина = время» — flamegraph — «высота = глубина стека» — flamegraph), оптимизировать узкие кадры (flamegraph — «узкий кадр — мало времени» — flamegraph — метрики — «оптимизировать широкие» — flamegraph — техдолг), flamegraph без контекста (flamegraph — «профиль без нагрузки» — flamegraph — метрики — «профилировать под нагрузкой» — flamegraph — performance testing).

Практика: генерация и анализ flamegraph

CPU flamegraph (Linux perf) (flamegraph: perf record -F 99 -a -g -- sleep 30 perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > cpu.svg (flamegraph — «perf → flamegraph.svg» — flamegraph — linux — Brendan Gregg (flamegraph — «FlameGraph» — flamegraph); py-spy (Python) (python: py-spy record -o profile.svg --pid 1234 (python — «py-spy — flamegraph Python» — python — flamegraph — «без изменения кода» — python); pprof (Go) (pprof: go tool pprof -http=:8080 cpu.prof (pprof — «pprof — flamegraph Go» — pprof — flamegraph — «веб-интерфейс» — pprof); Чтение (flamegraph: ищи широкие кадры (flamegraph — «широкий = много времени» — flamegraph — метрики — «плато» — flamegraph — «где время тратится» — flamegraph — linux); Pyroscope (continuous profiling: непрерывные профили (continuous profiling — «flamegraph в проде» — continuous profiling — flamegraph — «непрерывно» — continuous profiling — «история профилей» — continuous profiling).

Практический сценарий: оптимизация API по flamegraph

Контекст: API тормозит (метрики — p99 вырос (метрики — golden signals — «латентность» — golden signals — incident), USE показал CPU saturated (use-метод — «CPU saturated» — use-метод — flamegraph), боль: непонятно, какая функция (flamegraph — «какая функция жрёт CPU» — flamegraph — метрики — «гадание» — flamegraph); решение — flamegraph: (1) профиль под нагрузкой (flamegraph — «профилировать под нагрузкой» — flamegraph — performance testing — perf record (flamegraph — «perf record -F 99 -a -g -- sleep 30» — flamegraph — linux); (2) генерация (flamegraph — perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > cpu.svg (flamegraph — «cpu.svg» — flamegraph — linux); (3) чтение (flamegraph — ищи широкие кадры (flamegraph — «широкий = много времени» — flamegraph — метрики — «плато» — flamegraph — «serialize_json — 60% ширины» — flamegraph); (4) узкое место (flamegraph — serialize_json (flamegraph — «60% CPU» — flamegraph — метрики — «широкий кадр» — flamegraph); (5) оптимизация (flamegraph — кэш/быстрее библиотека (flamegraph — «orjson вместо json» — flamegraph — python — «оптимизировать широкое» — flamegraph); (6) differential (flamegraph — до/после (flamegraph — «serialize_json — 60% → 10%» — flamegraph — метрики — «улучшение видно» — flamegraph); (7) Pyroscope (continuous profiling — непрерывный профиль (continuous profiling — «flamegraph в проде» — continuous profiling — flamegraph — «регресс виден» — continuous profiling); результат: узкое место найдено (flamegraph — serialize_json 60% (flamegraph — «широкий кадр» — flamegraph — метрики — оптимизация (flamegraph — orjson (python — «60% → 10%» — flamegraph — p99 упал (метрики — «p99 500 → 200 мс» — метрики — golden signals); вывод: flamegraph решили задачу (узкое место визуально — flamegraph — ADR — «интерпретировать высоту» — антипаттерн — flamegraph — ширина = время — метрики — техдолг).

FAQ

Как читать flamegraph и что означает ширина кадров? Чтение (flamegraph — «оси» — flamegraph — метрики — ось X (flamegraph — «ширина = время/сэмплы» — flamegraph — метрики — «шире = больше времени» — flamegraph), ось Y (flamegraph — «глубина стека» — flamegraph — метрики — «выше = глубже» — flamegraph); ширина (flamegraph — «ширина = время» — flamegraph — метрики — «широкий кадр = узкое место» — flamegraph — «ищи широкие» — flamegraph — linux); главное: ширина, не высота (flamegraph — «высота = глубина стека» — flamegraph — метрики — «ширина = время» — flamegraph — «плато — где время» — flamegraph); «интерпретировать высоту» — антипаттерн (высота ≠ время — flamegraph — ширина = время — метрики — ADR — техдолг).

Какие типы flamegraph бывают и когда какой использовать? CPU flamegraph (flamegraph — «где тратится CPU» — flamegraph — метрики — «on-CPU» — flamegraph — perf/pprof (pprof — когда: CPU saturated (use-метод — «CPU» — use-метод); Memory/heap (flamegraph — «где allocating память» — flamegraph — метрики — «heap» — flamegraph — утечки — когда: память/утечки (flamegraph — «память» — утечки); Off-CPU (flamegraph — «где ждёт (IO/lock)» — flamegraph — метрики — «off-CPU» — flamegraph — когда: блокировки/IO (flamegraph — «ждёт» — flamegraph); Differential (flamegraph — «разница до/после» — flamegraph — метрики — когда: регресс/улучшение (flamegraph — «до/после» — flamegraph); «только CPU» — мало (память/off-CPU/differential — тоже важны — flamegraph — ADR — техдолг).

Какие инструменты генерируют flamegraph и чем они отличаются? perf + FlameGraph (flamegraph — Linux (flamegraph — «perf record → flamegraph» — flamegraph — linux — Brendan Gregg (flamegraph — «универсальный» — flamegraph); py-spy (python — Python (python — «py-spy — без изменения кода» — python — flamegraph — «просто» — python); pprof (pprof — Go (pprof — «pprof — flamegraph Go» — pprof — flamegraph — «go tool pprof» — pprof); Pyroscope (continuous profiling — continuous profiling (continuous profiling — «flamegraph в проде» — continuous profiling — flamegraph — «непрерывно» — continuous profiling); отличие: perf — универсальный (flamegraph — linux), py-spy — Python (python), pprof — Go (pprof), Pyroscope — continuous (continuous profiling — «выбор по языку/задаче» — flamegraph — ADR — техдолг).

Как правильно профилировать под нагрузкой и почему это важно? Правильно: под нагрузкой (flamegraph — «профилировать под нагрузкой» — flamegraph — performance testing — «реальная нагрузка — реальный профиль» — flamegraph — performance testing — «perf record под нагрузкой» — flamegraph); почему важно: без нагрузки профиль нерепрезентативен (flamegraph — «профиль без нагрузки — не то» — flamegraph — метрики — «узкие места видны под нагрузкой» — flamegraph — performance testing — «idle профиль — бесполезен» — flamegraph); как: load testing (performance testing — k6/JMeter (performance testing — «нагрузка» — performance testing — load testing — профилирование (flamegraph — perf/py-spy/pprof (pprof — «под нагрузкой» — flamegraph — performance testing); «профиль без нагрузки» — антипаттерн (нерепрезентативно — flamegraph — под нагрузкой — performance testing — ADR — техдолг).

Источники: Brendan Gregg (flamegraphs), py-spy, Go pprof — ссылки в шапке.