Как вы профилируете Go-приложения? Расскажите о своем опыте использования pprof.

Ответ

Да, я регулярно использую pprof — встроенный в стандартную библиотеку Go инструмент для профилирования. Он незаменим для поиска узких мест в производительности и утечек памяти.

Мой рабочий процесс обычно выглядит так:

1. Интеграция pprof в приложение:

Самый простой способ — импортировать пакет net/http/pprof, который автоматически регистрирует обработчики для профилирования в DefaultServeMux.

import (
    "log"
    "net/http"
    _ "net/http/pprof" // Важно: импорт с подчеркиванием
)

func main() {
    // ... основной код приложения

    // Запускаем сервер для pprof в отдельной горутине
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()

    // ...
}

2. Сбор данных:

После запуска приложения я могу собирать различные профили с помощью утилиты go tool pprof.

  • CPU Profile (профиль процессора): Показывает, какие функции тратят больше всего процессорного времени.
    # Собираем профиль в течение 30 секунд
    go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
  • Heap Profile (профиль кучи): Показывает, какие функции аллоцируют больше всего памяти.
    go tool pprof http://localhost:6060/debug/pprof/heap

3. Анализ и Визуализация:

Самый удобный способ анализа — запустить pprof с веб-интерфейсом.

go tool pprof -http=:8081 profile.pb.gz

Это открывает браузер с интерактивным интерфейсом, где я могу анализировать:

  • Flame Graph (Пламенный граф): Лучший инструмент для визуализации узких мест в CPU.
  • Top: Список функций, отсортированных по потреблению ресурса.
  • Source: Позволяет посмотреть на исходный код с аннотациями по потреблению ресурсов для каждой строки.

Помимо CPU и heap, я также использовал pprof для анализа количества горутин (goroutine) и профиля блокировок (block), чтобы находить проблемы с конкурентностью.