Spec-Zone.ru › Go

Пакет pprof

  • import "runtime/pprof"
  • Обзор
  • Индекс

Обзор

Пакет pprof записывает данные профилирования выполнения в формате, ожидаемом инструментом визуализации pprof.

Профилирование программы Go

Первый шаг для профилирования программы Go — это включение профилирования. Поддержка профилирования бенчмарков, созданных с помощью стандартного пакета тестирования, встроена в go test. Например, следующая команда выполняет бенчмарки в текущем каталоге и записывает профили ЦП и памяти в cpu.prof и mem.prof:

go test -cpuprofile cpu.prof -memprofile mem.prof -bench .

Для добавления аналогичной поддержки профилирования в самостоятельную программу, добавьте код, подобный следующему, в вашу функцию main:

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")

func main() {
    flag.Parse()
    if *cpuprofile != "" {
        f, err := os.Create(*cpuprofile)
        if err != nil {
            log.Fatal("could not create CPU profile: ", err)
        }
        defer f.Close() // error handling omitted for example
        if err := pprof.StartCPUProfile(f); err != nil {
            log.Fatal("could not start CPU profile: ", err)
        }
        defer pprof.StopCPUProfile()
    }

    // ... rest of the program ...

    if *memprofile != "" {
        f, err := os.Create(*memprofile)
        if err != nil {
            log.Fatal("could not create memory profile: ", err)
        }
        defer f.Close() // error handling omitted for example
        runtime.GC() // get up-to-date statistics
        if err := pprof.WriteHeapProfile(f); err != nil {
            log.Fatal("could not write memory profile: ", err)
        }
    }
}

Также существует стандартный HTTP-интерфейс для данных профилирования. Добавление следующей строки установит обработчики по URL /debug/pprof/ для скачивания текущих профилей:

import _ "net/http/pprof"

Дополнительные сведения см. в пакете net/http/pprof.

Профили можно визуализировать с помощью инструмента pprof:

go tool pprof cpu.prof

Из командной строки pprof доступно множество команд. Часто используемые команды включают "top", которая выводит сводку наиболее ресурсоёмких участков программы, и "web", которая открывает интерактивную диаграмму наиболее ресурсоёмких участков и их вызовов. Используйте "help", чтобы получить информацию обо всех командах pprof.

Для получения дополнительной информации о pprof, см. https://github.com/google/pprof/blob/main/doc/README.md.

Индекс

  • func Do(ctx context.Context, labels LabelSet, f func(context.Context))
  • func ForLabels(ctx context.Context, f func(key, value string) bool)
  • func Label(ctx context.Context, key string) (string, bool)
  • func SetGoroutineLabels(ctx context.Context)
  • func StartCPUProfile(w io.Writer) error
  • func StopCPUProfile()
  • func WithLabels(ctx context.Context, labels LabelSet) context.Context
  • func WriteHeapProfile(w io.Writer) error
  • тип LabelSet
  • func Labels(args ...string) LabelSet
  • тип Profile
  • func Lookup(name string) *Profile
  • func NewProfile(name string) *Profile
  • func Profiles() []*Profile
  • func (p *Profile) Add(value any, skip int)
  • func (p *Profile) Count() int
  • func (p *Profile) Name() string
  • func (p *Profile) Remove(value any)
  • func (p *Profile) WriteTo(w io.Writer, debug int) error
  • Ошибки

Файлы пакета

elf.go label.go map.go pe.go pprof.go pprof_rusage.go proto.go proto_other.go protobuf.go protomem.go runtime.go

func Do 1.9

func Do(ctx context.Context, labels LabelSet, f func(context.Context))

Do вызывает f с копией родительского контекста, к которому добавлены указанные метки в карту меток родителя. Потоки, запущенные во время выполнения f, унаследуют расширенный набор меток. Каждая пара ключ/значение в метках вставляется в карту меток в указанном порядке, перезаписывая любое предыдущее значение для того же ключа. Расширенная карта меток будет установлена на время вызова f и восстановлена после возвращения f.

func ForLabels 1.9

func ForLabels(ctx context.Context, f func(key, value string) bool)

ForLabels вызывает f с каждым набором меток в контексте. Функция f должна возвращать true, чтобы продолжить итерацию, или false, чтобы остановить итерацию досрочно.

func Label 1.9

func Label(ctx context.Context, key string) (string, bool)

Label возвращает значение метки с заданным ключом в ctx и булево значение, указывающее, существует ли эта метка.

func SetGoroutineLabels 1.9

func SetGoroutineLabels(ctx context.Context)

SetGoroutineLabels устанавливает метки текущего потока в соответствии с ctx. Новый поток наследует метки потока, который его создал. Это API более низкого уровня, чем Do, который следует использовать вместо него, когда это возможно.

func StartCPUProfile

func StartCPUProfile(w io.Writer) error

StartCPUProfile включает профилирование ЦП для текущего процесса. Во время профилирования профиль будет буферизован и записан в w. StartCPUProfile возвращает ошибку, если профилирование уже включено.

В системах Unix StartCPUProfile по умолчанию не работает для кода Go, построенного с помощью -buildmode=c-archive или -buildmode=c-shared. StartCPUProfile полагается на сигнал SIGPROF, но этот сигнал будет доставлен обработчику сигнала SIGPROF основной программы (если есть), а не обработчику, используемому Go. Для его работы вызовите os/signal.Notify для syscall.SIGPROF, но обратите внимание, что это может нарушить любое профилирование, выполняемое основной программой.

func StopCPUProfile

func StopCPUProfile()

StopCPUProfile останавливает текущий профиль ЦП, если он есть. StopCPUProfile возвращает только после завершения всех записей профиля.

func WithLabels 1.9

func WithLabels(ctx context.Context, labels LabelSet) context.Context

WithLabels возвращает новый контекст context.Context с добавленными метками. Метка перезаписывает предыдущую метку с тем же ключом.

func WriteHeapProfile

func WriteHeapProfile(w io.Writer) error

WriteHeapProfile — это сокращение для Lookup("heap").WriteTo(w, 0). Оно сохраняется для обратной совместимости.

тип LabelSet 1.9

LabelSet — это набор меток.

type LabelSet struct {
    // contains filtered or unexported fields
}

func Labels 1.9

func Labels(args ...string) LabelSet

Labels принимает четное количество строк, представляющих пары ключ-значение, и создает LabelSet, содержащий их. Метка перезаписывает предыдущую метку с тем же ключом. В настоящее время только профили ЦП и потоков используют информацию о метках. Подробности см. на https://golang.org/issue/23458.

тип Profile

Profile — это набор стековых следов, показывающих последовательность вызовов, приведших к экземплярам определенного события, такого как выделение. Пакеты могут создавать и поддерживать свои собственные профили; наиболее распространенное использование — отслеживание ресурсов, которые необходимо явно закрыть, таких как файлы или сетевые соединения.

Методы Profile могут вызываться из нескольких потоков одновременно.

Каждый Profile имеет уникальное имя. Несколько профилей определены заранее:

goroutine    - stack traces of all current goroutines
heap         - a sampling of memory allocations of live objects
allocs       - a sampling of all past memory allocations
threadcreate - stack traces that led to the creation of new OS threads
block        - stack traces that led to blocking on synchronization primitives
mutex        - stack traces of holders of contended mutexes

Эти заранее определённые профили поддерживают себя и вызывают панику при явном вызове метода Profile.Add или Profile.Remove.

Профиль ЦП недоступен как Profile. У него есть специальный API, функции StartCPUProfile и StopCPUProfile, поскольку он передает вывод в писатель во время профилирования.

Профиль кучи

Профиль кучи сообщает статистику по состоянию на последнюю завершённую сборку мусора; он опускает более поздние выделения, чтобы избежать искажения профиля от живых данных в сторону мусора. Если сборка мусора не происходила, профиль кучи сообщает обо всех известных выделениях. Это исключение помогает в основном в программах, работающих без включённой сборки мусора, обычно в целях отладки.

Профиль кучи отслеживает место выделения всех живых объектов в памяти приложения и всех объектов, выделенных с момента запуска программы. Флаги pprof -inuse_space, -inuse_objects, -alloc_space и -alloc_objects выбирают, что отображать, по умолчанию -inuse_space (живые объекты, масштабируемые по размеру).

Профиль выделений

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

Профиль блокировок

Профиль блокировок отслеживает время, затраченное на блокировку на синхронизирующих примитивах, таких как sync.Mutex, sync.RWMutex, sync.WaitGroup, sync.Cond и отправка/прием/выбор по каналу.

Стековые следы соответствуют месту блокировки (например, sync.Mutex.Lock).

Образцы соответствуют суммарному времени, затраченному на блокировку в этом стековом следе, с учётом выборочного измерения по времени, заданного runtime.SetBlockProfileRate.

Профиль мьютексов

Профиль мьютексов отслеживает конкуренцию за мьютексы, такие как sync.Mutex, sync.RWMutex и внутренние блокировки runtime.

Стековые следы соответствуют окончанию критической секции, вызывающей конкуренцию. Например, блокировка, удерживаемая в течение долгого времени, в то время как другие потоки ожидают её захвата, будет сообщать о конкуренции при окончательном разблокировании (то есть, в sync.Mutex.Unlock).

Образцы соответствуют приблизительному суммарному времени, затраченному другими потоками на ожидание блокировки, с учётом выборочного измерения по событиям, заданного runtime.SetMutexProfileFraction. Например, если вызывающий удерживает блокировку 1 секунду, в то время как 5 других потоков ожидают весь этот секунду, чтобы захватить блокировку, стек вызова разблокирования будет сообщать о 5 секундах конкуренции.

Внутренние блокировки runtime всегда отображаются в местоположении "runtime._LostContendedRuntimeLock". Более подробные стековые следы для внутренних блокировок runtime можно получить, установив `GODEBUG=runtimecontentionstacks=1` (см. документацию пакета runtime для замечаний).

type Profile struct {
    // contains filtered or unexported fields
}

func Lookup

func Lookup(name string) *Profile

Lookup возвращает профиль с заданным именем или nil, если такой профиль не существует.

func NewProfile

func NewProfile(name string) *Profile

NewProfile создаёт новый профиль с заданным именем. Если профиль с таким именем уже существует, NewProfile вызывает панику. Для обеспечения совместимости с различными инструментами, которые считывают данные pprof, имена профилей не должны содержать пробелов.

func Profiles

func Profiles() []*Profile

Profiles возвращает срез всех известных профилей, отсортированных по имени.

func (*Profile) Add

func (p *Profile) Add(value any, skip int)

Add добавляет текущий стек вызовов в профиль, связанный со значением. Add сохраняет значение во внутренней карте, поэтому значение должно быть подходящим для использования в качестве ключа карты и не будет удалено сборщиком мусора до соответствующего вызова Profile.Remove. Add вызывает панику, если профиль уже содержит стек для значения.

Параметр skip имеет то же значение, что и skip в runtime.Caller, и определяет, с какой точки стека начинается трассировка. Передача skip=0 начинает трассировку с вызова функции Add. Например, при таком стеке вызовов:

Add
called from rpc.NewClient
called from mypkg.Run
called from main.main

Передача skip=0 начинает трассировку с вызова Add внутри rpc.NewClient. Передача skip=1 начинает трассировку с вызова NewClient внутри mypkg.Run.

func (*Profile) Count

func (p *Profile) Count() int

Count возвращает количество стеков выполнения, текущих в профиле.

func (*Profile) Name

func (p *Profile) Name() string

Name возвращает имя этого профиля, которое можно передать в Lookup для повторного получения профиля.

func (*Profile) Remove

func (p *Profile) Remove(value any)

Remove удаляет стек выполнения, связанный со значением, из профиля. Это ничего не делает, если значение не находится в профиле.

func (*Profile) WriteTo

func (p *Profile) WriteTo(w io.Writer, debug int) error

WriteTo записывает в w дамп профиля в формате pprof. Если запись в w возвращает ошибку, WriteTo возвращает эту ошибку. В противном случае WriteTo возвращает nil.

Параметр debug включает дополнительный вывод. Передача debug=0 записывает сжатый gzip протокол, описанный в https://github.com/google/pprof/tree/main/proto#overview. Передача debug=1 записывает устаревший текстовый формат с комментариями, преобразующими адреса в имена функций и номера строк, чтобы программист мог прочитать профиль без инструментов.

Предварительно определённые профили могут назначать значения параметру debug; например, при печати профиля «goroutine», debug=2 означает печать стеков goroutine в том же формате, что и Go-программа использует при завершении из-за необработанной паники.

Ошибки

  • ☞

    Профили так же хороши, как и поддержка ядра, используемая для их создания. Подробности о известных проблемах можно найти в https://golang.org/issue/13841.

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/runtime/pprof/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API