Функция pprof.Lookup

Функция pprof.Lookup из пакета runtime/pprof используется для получения профиля выполнения программы по его имени. Она принимает строковое имя профиля и возвращает объект типа *Profile, либо nil, если профиль с таким именем не зарегистрирован. Эта функция полезна для сбора данных о производительности в тестах и бенчмарках.

Синтаксис

gopprof.Lookup(name string) *pprof.Profile

Доступные профили

Пакет runtime/pprof предоставляет следующие стандартные профили:

gogoroutine  - текущие горутины
heap     - распределение памяти
threadcreate - создание потоков
block    - блокировки синхронизации
mutex    - блокировки мьютексов
allocs     - все распределения памяти

Пример получения профиля горутин

Рассмотрим пример получения профиля горутин и записи его в буфер:

gopackage main

import (
  "bytes"
  "fmt"
  "runtime/pprof"
)

func main() {
  profile := pprof.Lookup("goroutine")
  if profile == nil {
    fmt.Println("profile not found")
    return
  }

  var buf bytes.Buffer
  err := profile.WriteTo(&buf, 1)
  if err != nil {
    fmt.Println("write error:", err)
    return
  }

  fmt.Println("goroutine profile length:", buf.Len())
}

Результат выполнения кода:

go"goroutine profile length: 1024"

Пример профилирования кучи

Получим профиль кучи и сохраним его в файл для дальнейшего анализа:

gopackage main

import (
  "fmt"
  "os"
  "runtime/pprof"
)

func main() {
  profile := pprof.Lookup("heap")
  if profile == nil {
    fmt.Println("heap profile not found")
    return
  }

  file, err := os.Create("heap.prof")
  if err != nil {
    fmt.Println("create file error:", err)
    return
  }
  defer file.Close()

  err = profile.WriteTo(file, 0)
  if err != nil {
    fmt.Println("write error:", err)
    return
  }

  fmt.Println("heap profile saved to heap.prof")
}

Результат выполнения кода:

go"heap profile saved to heap.prof"

Пример с бенчмарком

Рассмотрим использование pprof.Lookup в бенчмарке для анализа аллокаций памяти:

gopackage main

import (
  "fmt"
  "runtime/pprof"
  "testing"
)

func BenchmarkAllocs(b *testing.B) {
  profile := pprof.Lookup("allocs")
  if profile == nil {
    b.Fatal("allocs profile not found")
  }

  var total int64
  for i := 0; i < b.N; i++ {
    s := make([]int, 100)
    total += int64(len(s))
  }

  fmt.Println("Total allocations:", total)
}

Пример проверки наличия профиля

Проверим, зарегистрирован ли профиль с определенным именем:

gopackage main

import (
  "fmt"
  "runtime/pprof"
)

func main() {
  profiles := []string{
    "goroutine",
    "heap",
    "custom",
  }

  for _, name := range profiles {
    profile := pprof.Lookup(name)
    if profile == nil {
      fmt.Printf("profile '%s' not found\n", name)
    } else {
      fmt.Printf("profile '%s' found, count: %d\n",
        name, profile.Count())
    }
  }
}

Результат выполнения кода:

go"profile 'goroutine' found, count: 1"
"profile 'heap' found, count: 0"
"profile 'custom' not found"

Смотрите также

  • функцию pprof.StartCPUProfile,
    которая начинает запись профиля CPU
  • функцию pprof.StopCPUProfile,
    которая останавливает запись профиля CPU
  • функцию pprof.WriteHeapProfile,
    которая записывает профиль кучи в вывод
  • пакет net/http/pprof,
    который предоставляет HTTP-интерфейс для профилирования