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

Главная → Статьи → Профилирование Go: pprof на практике

Профилирование Go-приложений: pprof для CPU, памяти и блокировок

Как профилировать Go-приложения через pprof: CPU/heap/goroutine/block профили, net/http/pprof, чтение flamegraph и практические паттерны оптимизации.

Прямой ответ

pprof — инструмент профилирования Go-приложений (pprof — «профили CPU/памяти/goroutines» — pprof — метрики — «где Go-приложение тратит ресурсы» — pprof), зачем: найти узкое место в Go-коде (pprof — «какая функция жрёт CPU/память» — pprof — метрики — «не гадать, а видеть» — pprof — flamegraph — «визуально» — pprof); подключение (pprof — net/http/pprof (pprof — import _ "net/http/pprof" go func() { http.ListenAndServe("localhost:6060", nil) }() (pprof — «pprof на :6060» — pprof — метрики — «эндпоинты /debug/pprof/» — pprof); типы профилей (pprof): (1) CPU profile (pprof — «где тратится CPU» — pprof — метрики — go tool pprof (pprof — «30 с CPU профиль» — pprof — [flamegraph](./flamegraph-analiz-proizvoditelnosti.md) — «on-CPU» — pprof); (2) **Heap profile** (pprof — «где allocating память» — pprof — [метрики](./prometheus-instrumentatsiya-prilozheniya-metriki.md) — go tool pprof (pprof — «heap профиль» — pprof — утечки — «утечки памяти» — pprof); (3) Goroutine profile (pprof — «где goroutines» — pprof — метрики — go tool pprof (pprof — «goroutines» — pprof — «утечки goroutines» — pprof); (4) **Block profile** (pprof — «где блокировки» — pprof — [метрики](./prometheus-instrumentatsiya-prilozheniya-metriki.md) — go tool pprof (pprof — «блокировки» — pprof — «mutex/channel» — pprof); (5) Mutex profile (pprof — «где mutex contention» — pprof — метрики — go tool pprof (pprof — «mutex» — pprof — «конкуренция за блокировки» — pprof); **чтение профилей** (pprof — интерактив (pprof — go tool pprof -http=:8080 cpu.prof` (pprof — «веб-интерфейс» — pprof — flamegraph — flamegraph (flamegraph — «широкие кадры» — flamegraph — pprof — top/list (pprof — «top — топ функций, list — по строкам» — pprof — метрики); continuous profiling (continuous profiling — Pyroscope (continuous profiling — «pprof в проде непрерывно» — continuous profiling — pprof — «непрерывные профили» — continuous profiling — «история» — continuous profiling); когда pprof: Go-сервис тормозит (pprof — «где узкое место» — pprof — метрики — use-метод — «CPU/память saturated» — use-метод), оптимизация (pprof — «что оптимизировать» — pprof — метрики — «широкие кадры» — flamegraph), утечки (pprof — «утечки памяти/goroutines» — pprof — утечки — heap/goroutine (pprof — «утечки» — pprof); антипаттерны: pprof в проде без защиты (pprof — «pprof открыт» — pprof — OWASP — «/debug/pprof — уязвимость» — OWASP — только localhost/internal — pprof), профиль без нагрузки (pprof — «профиль без нагрузки» — pprof — метрики — «под нагрузкой» — pprof — performance testing), игнорировать goroutine/block (pprof — «только CPU» — pprof — метрики — «goroutine/block — тоже» — pprof — техдолг).

Практика: профилирование Go-приложения

Подключение pprof (pprof: package main import ( _ "net/http/pprof" "net/http" ) func main() { go func() { http.ListenAndServe("localhost:6060", nil) }() // приложение } (pprof — «pprof на localhost:6060» — pprof — метрики — только localhost (pprof — «не наружу» — OWASP); CPU профиль (pprof: go tool pprof (pprof — «30 с CPU» — pprof — [flamegraph](./flamegraph-analiz-proizvoditelnosti.md) — под нагрузкой (pprof — «под нагрузкой» — pprof — [performance testing](./performance-testing-metodologiya.md)); **Heap профиль** (pprof: go tool pprof (pprof — «heap» — pprof — утечки — «утечки памяти» — pprof); Goroutine профиль (pprof: go tool pprof (pprof — «goroutines» — pprof — «утечки goroutines» — pprof); **Веб-интерфейс** (pprof: go tool pprof -http=:8080 cpu.prof` (pprof — «веб» — pprof — flamegraph — flamegraph (flamegraph — «широкие кадры» — flamegraph — pprof); Pyroscope (continuous profiling: непрерывный профиль (continuous profiling — «pprof в проде» — continuous profiling — pprof — «непрерывно» — continuous profiling).

Практический сценарий: оптимизация Go-сервиса через pprof

Контекст: Go-сервис (pprof), боль: CPU saturated (use-метод — «CPU saturated» — use-метод — pprof — p99 вырос (метрики — golden signals — «латентность» — golden signals — incident), непонятно, какая функция (pprof — «какая функция» — pprof — метрики); решение — pprof: (1) подключение (pprof — net/http/pprof (pprof — go func() { http.ListenAndServe("localhost:6060", nil) }() (pprof — «pprof на localhost» — pprof — OWASP); (2) CPU профиль (pprof — go tool pprof (pprof — «30 с под нагрузкой» — pprof — [performance testing](./performance-testing-metodologiya.md)); (3) веб-интерфейс (pprof — go tool pprof -http=:8080 cpu.prof(pprof — «веб» — pprof — [flamegraph](./flamegraph-analiz-proizvoditelnosti.md) — flamegraph ([flamegraph](./flamegraph-analiz-proizvoditelnosti.md) — «широкие кадры» — [flamegraph](./flamegraph-analiz-proizvoditelnosti.md)); (4) узкое место (pprof —json.Marshal(pprof — «50% CPU» — pprof — [метрики](./prometheus-instrumentatsiya-prilozheniya-metriki.md) — «широкий кадр» — [flamegraph](./flamegraph-analiz-proizvoditelnosti.md)); (5) оптимизация (pprof — faster JSON (pprof — «json-iterator вместо json» — pprof — [flamegraph](./flamegraph-analiz-proizvoditelnosti.md) — «оптимизировать широкое» — [flamegraph](./flamegraph-analiz-proizvoditelnosti.md)); (6) heap (pprof —go tool pprof (pprof — «heap» — pprof — утечки — «аллокации» — pprof); (7) Pyroscope (continuous profiling — непрерывный профиль (continuous profiling — «pprof в проде» — continuous profiling — pprof — «регресс виден» — continuous profiling); результат: узкое место найдено (pprof — json.Marshal 50% (pprof — «широкий кадр» — flamegraph — оптимизация (pprof — json-iterator (pprof — «50% → 10%» — pprof — p99 упал (метрики — «p99 500 → 200 мс» — метрики — golden signals); вывод: pprof решили задачу (узкое место в Go-коде — pprof — ADR — «pprof в проде без защиты» — антипаттерн — OWASP — только localhost — pprof — техдолг).

FAQ

Что такое pprof и какие типы профилей он даёт? pprof (pprof — инструмент профилирования Go (pprof — «профили CPU/памяти/goroutines» — pprof — метрики — «где Go тратит ресурсы» — pprof); типы: CPU (pprof — «где тратится CPU» — pprof — метрики), Heap (pprof — «где allocating память» — pprof — утечки), Goroutine (pprof — «где goroutines» — pprof — «утечки goroutines» — pprof), Block (pprof — «где блокировки» — pprof — «mutex/channel» — pprof), Mutex (pprof — «где mutex contention» — pprof — «конкуренция» — pprof); подключение: net/http/pprof (pprof — import _ "net/http/pprof" (pprof — «эндпоинты /debug/pprof/» — pprof — метрики); «только CPU» — мало (heap/goroutine/block — тоже — pprof — ADR — техдолг).

Как читать профили pprof и что такое flamegraph в pprof? Чтение (pprof — интерактив (pprof — go tool pprof -http=:8080 cpu.prof (pprof — «веб-интерфейс» — pprof — flamegraph — top (pprof — «топ функций» — pprof — метрики), list (pprof — «по строкам» — pprof — метрики); Flamegraph (flamegraph — «визуализация стеков» — flamegraph — pprof — «широкие кадры» — flamegraph — pprof — «ширина = время» — flamegraph — «ищи широкие» — flamegraph — pprof); как: веб-интерфейс (pprof — -http=:8080 (pprof — «веб» — pprof — flamegraph — flamegraph (flamegraph — «широкие кадры» — flamegraph — pprof — top/list (pprof — «детали» — pprof); «pprof без flamegraph» — мало (визуально быстрее — flamegraph — flamegraph обязателен — flamegraph — ADR — техдолг).

Как найти утечки памяти и goroutines через pprof? Утечки памяти (pprof — heap профиль (pprof — go tool pprof (pprof — «heap» — pprof — [утечки](./utechki-pamyati-python-poisk-ustranenie.md) — «что allocating» — pprof — «inuse_space» — pprof — [утечки](./utechki-pamyati-python-poisk-ustranenie.md)); Утечки goroutines (pprof — goroutine профиль (pprof — go tool pprof (pprof — «goroutines» — pprof — «много goroutines — утечка» — pprof — утечки — «где созданы» — pprof); как: heap (pprof — «inuse_space» (pprof — утечки — «что держит память» — pprof), goroutine (pprof — «много goroutines» (pprof — утечки — «где созданы» — pprof), Pyroscope (continuous profiling — «история профилей» — continuous profiling — pprof — «рост виден» — continuous profiling); «утечки без pprof» — сложно (heap/goroutine — обязательны — pprof — утечки — ADR — техдолг).

Можно ли держать pprof в проде и как делать безопасно? Можно, но с защитой (pprof — «pprof в проде» — pprof — OWASP — «/debug/pprof — уязвимость» — OWASP — «открытый pprof — информация/DoS» — OWASP); безопасно: только localhost (pprof — http.ListenAndServe("localhost:6060", nil) (pprof — «не наружу» — pprof — OWASP), internal-сеть (pprof — «pprof на internal-интерфейсе» — pprof — OWASP — «не публичный» — pprof), auth (pprof — «pprof за auth» — pprof — OWASP — «не авторизован — не пускать» — OWASP), Pyroscope (continuous profiling — «pprof через Pyroscope» — continuous profiling — pprof — «безопаснее» — continuous profiling); «pprof открыт в проде» — антипаттерн (уязвимость — OWASP — localhost/internal/auth — pprof — ADR — техдолг).

Источники: Go blog (pprof), runtime/pprof docs, Go diagnostics — ссылки в шапке.