Перейти до змісту

go tool trace — трейсер виконання

go tool trace — це інструмент перегляду трейсів виконання (execution traces), що виробляються трейсером Go runtime (пакет runtime/trace). Трейс — це бінарний журнал низькорівневих подій runtime із наносекундними мітками часу та стеками викликів.

Трейсер проти профайлера

Трейсер — це не профайлер. З офіційної сторінки діагностики:

"However, it is not great for identifying hot spots such as analyzing the cause of excessive memory or CPU usage. Use profiling tools instead first to address them."

  • pprof відповідає на питання «де моя програма витрачає CPU або виділяє пам'ять?» через статистичні вибірки.
  • go tool trace відповідає на питання «як взаємодіють мої горутини з плином часу?» — планування, блокування, паузи GC, системні виклики, суперечка за ресурси, паралелізм. Це погляд на часову шкалу.

Що записує трейсер

Відповідно до документації пакету runtime/trace:

  • Створення, блокування та розблокування горутин
  • Події входу / виходу / блокування системних викликів (syscall)
  • Події GC
  • Зміни розміру купи (heap)
  • Події запуску/зупинки процесора (P)
  • Зразки CPU-профілювання (коли активні)
  • Необов'язкові анотації користувача:
  • Tasks — логічні операції, що охоплюють кілька горутин
  • Regions — часові інтервали всередині однієї горутини; можуть бути вкладеними
  • Logs — повідомлення з мітками часу та категоріями

Як отримати трейс

Існують три поширені способи.

A. З коду

Оберніть навантаження, яке хочете трейсувати, у trace.Start та trace.Stop:

package main

import (
    "log"
    "os"
    "runtime/trace"
)

func main() {
    f, err := os.Create("trace.out")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    if err := trace.Start(f); err != nil {
        log.Fatal(err)
    }
    defer trace.Stop()

    // ... навантаження для трейсування ...
}

B. З тестів

Найпростіший шлях — без змін у коді:

go test -trace=trace.out ./...

C. З працюючого сервера

Імпортуйте net/http/pprof, і сервер відкриє /debug/pprof/trace?seconds=5, що стримить 5-секундний трейс:

import _ "net/http/pprof"

Далі:

curl -o trace.out 'http://localhost:6060/debug/pprof/trace?seconds=5'

Перегляд трейсу

go tool trace trace.out

Це запускає локальний вебсервер та відкриває браузер. Інтерфейс пропонує кілька представлень:

  • View trace — часова шкала. Горутини по осі Y, час по осі X, події з кольоровим кодуванням. Можна наближати до окремих переходів стану горутини.
  • Goroutine analysis — розбивка за горутинами: скільки часу витрачено в різних станах (виконання, блокування системним викликом, блокування примітивом синхронізації, блокування планувальником тощо).
  • Network / sync / syscall / scheduler blocking profiles — розбивки у стилі flame-graph: чому горутини очікували.
  • User-defined tasks/regions — з'являється, коли ваш код використовував trace.NewTask або trace.WithRegion.

Коли варто використовувати

  • Ви підозрюєте суперечку горутин або низький паралелізм.
  • Хвостова затримка (tail latency) є поганою, і ви хочете побачити паузи GC на часовій шкалі.
  • Ви додали конкурентність, але пропускна здатність не зросла, і хочете перевірити, чи горутини справді виконуються паралельно.
  • Запит іноді займає значно більше часу, ніж зазвичай, і ви хочете бачити, що його заблокувало.

Якщо «цей код у середньому повільний», спочатку звертайтесь до go tool pprof.

Джерела