Go runtime/trace 包详解
概述
runtime/trace 包包含为 Go 执行跟踪器生成跟踪的工具。
重要说明:
- 捕获广泛的执行事件(goroutine 创建/阻塞/解除阻塞、系统调用、GC 事件等)
- 为大多数事件捕获纳秒级时间戳和堆栈跟踪
- 可通过
go tool trace工具分析和可视化 - 支持用户注释(日志、区域、任务)
- 与
net/http/pprof包配合提供 HTTP 接口
跟踪的事件类型:
- Goroutine 创建/阻塞/解除阻塞
- 系统调用进入/退出/阻塞
- GC 相关事件
- 堆大小变化
- 处理器启动/停止
- CPU 分析样本(如果启用)
包导入
import "runtime/trace"
基本使用
示例 1:基本跟踪
package main
import (
"os"
"runtime/trace"
)
func main() {
// 启用跟踪
trace.Start(os.Stdout)
defer trace.Stop()
// ... 程序的其余部分 ...
}
运行命令:
# 运行程序并生成跟踪文件
go run main.go > trace.out
# 使用 trace 工具分析
go tool trace trace.out
示例 2:完整的跟踪程序
package main
import (
"fmt"
"os"
"runtime/trace"
"time"
)
func main() {
f, err := os.Create("trace.out")
if err != nil {
panic(err)
}
defer f.Close()
if err := trace.Start(f); err != nil {
panic(err)
}
defer trace.Stop()
// 执行一些工作
work()
fmt.Println("Trace written to trace.out")
fmt.Println("Run: go tool trace trace.out")
}
func work() {
// 模拟工作
time.Sleep(100 * time.Millisecond)
}
函数详解(按 a-z 排序)
IsEnabled
func IsEnabled() bool
说明:报告是否启用了跟踪。此信息仅供参考,跟踪状态可能在此函数返回时已更改。
使用示例:
package main
import (
"fmt"
"runtime/trace"
)
func main() {
fmt.Printf("Tracing enabled: %v\n", trace.IsEnabled())
trace.Start(os.Stdout)
defer trace.Stop()
fmt.Printf("Tracing enabled: %v\n", trace.IsEnabled())
}
运行结果:
Tracing enabled: false
Tracing enabled: true
Log
func Log(ctx context.Context, category, message string)
说明:发出带有给定类别和消息的时间戳事件。
使用示例:
package main
import (
"context"
"runtime/trace"
"time"
)
func processOrder(ctx context.Context, orderID string) {
trace.Log(ctx, "order", "Processing order: "+orderID)
// 处理订单
time.Sleep(10 * time.Millisecond)
trace.Log(ctx, "order", "Completed order: "+orderID)
}
func main() {
ctx := context.Background()
trace.Start(os.Stdout)
defer trace.Stop()
processOrder(ctx, "ORD-123")
processOrder(ctx, "ORD-456")
}
Logf
func Logf(ctx context.Context, category, format string, args ...interface{})
说明:类似于 Log,但使用指定的格式说明符格式化值。
使用示例:
package main
import (
"context"
"runtime/trace"
)
func processItem(ctx context.Context, id, quantity int) {
trace.Logf(ctx, "inventory", "Processing item %d, quantity: %d", id, quantity)
// 处理物品
}
func main() {
ctx := context.Background()
trace.Start(os.Stdout)
defer trace.Stop()
for i := 0; i < 10; i++ {
processItem(ctx, i, i*10)
}
}
Start
func Start(w io.Writer) error
说明:为当前程序启用跟踪。跟踪期间,跟踪数据将被缓冲并写入 w。
使用示例:
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()
// ... 程序的其余部分 ...
}
Stop
func Stop()
说明:停止当前的跟踪(如果有的话)。仅在所有跟踪写入完成后才返回。
使用示例:参见 Start 函数示例。
WithRegion
func WithRegion(ctx context.Context, regionType string, fn func())
说明:启动与调用 goroutine 关联的区域,运行 fn,然后结束区域。
使用示例:
package main
import (
"context"
"runtime/trace"
"time"
)
func makeCappuccino(ctx context.Context) {
trace.WithRegion(ctx, "makeCappuccino", func() {
trace.Log(ctx, "step", "Starting cappuccino")
trace.WithRegion(ctx, "steamMilk", func() {
time.Sleep(10 * time.Millisecond)
})
trace.WithRegion(ctx, "extractCoffee", func() {
time.Sleep(15 * time.Millisecond)
})
trace.WithRegion(ctx, "mixMilkCoffee", func() {
time.Sleep(5 * time.Millisecond)
})
trace.Log(ctx, "step", "Cappuccino ready")
})
}
func main() {
ctx := context.Background()
trace.Start(os.Stdout)
defer trace.Stop()
makeCappuccino(ctx)
}
类型详解
FlightRecorder
type FlightRecorder struct{}
说明:表示 Go 执行跟踪的单个消费者。它跟踪运行时生成的执行跟踪的移动窗口,始终包含最近的跟踪数据。
NewFlightRecorder
func NewFlightRecorder(cfg FlightRecorderConfig) *FlightRecorder
说明:从提供的配置创建新的飞行记录器。
使用示例:
package main
import (
"os"
"runtime/trace"
"time"
)
func main() {
// 创建飞行记录器
fr := trace.NewFlightRecorder(trace.FlightRecorderConfig{})
if err := fr.Start(); err != nil {
panic(err)
}
// 运行一段时间
time.Sleep(1 * time.Second)
// 写入跟踪数据
f, _ := os.Create("flight.out")
defer f.Close()
fr.WriteTo(f)
fr.Stop()
}
Enabled
func (fr *FlightRecorder) Enabled() bool
说明:如果飞行记录器处于活动状态则返回 true。
使用示例:
package main
import (
"fmt"
"runtime/trace"
)
func main() {
fr := trace.NewFlightRecorder(trace.FlightRecorderConfig{})
fmt.Printf("Before start: %v\n", fr.Enabled())
fr.Start()
fmt.Printf("After start: %v\n", fr.Enabled())
fr.Stop()
fmt.Printf("After stop: %v\n", fr.Enabled())
}
运行结果:
Before start: false
After start: true
After stop: false
Start
func (fr *FlightRecorder) Start() error
说明:激活飞行记录器并开始记录跟踪数据。
使用示例:参见 NewFlightRecorder 示例。
Stop
func (fr *FlightRecorder) Stop()
说明:结束跟踪数据的记录。
使用示例:参见 NewFlightRecorder 示例。
WriteTo
func (fr *FlightRecorder) WriteTo(w io.Writer) (int64, error)
说明:快照飞行记录器跟踪的移动窗口。
使用示例:
package main
import (
"os"
"runtime/trace"
"time"
)
func main() {
fr := trace.NewFlightRecorder(trace.FlightRecorderConfig{})
fr.Start()
defer fr.Stop()
// 模拟工作
time.Sleep(100 * time.Millisecond)
// 写入当前窗口的跟踪数据
f, _ := os.Create("snapshot.out")
defer f.Close()
n, err := fr.WriteTo(f)
if err != nil {
panic(err)
}
println("Written bytes:", n)
}
FlightRecorderConfig
type FlightRecorderConfig struct{}
说明:飞行记录器配置。目前为空结构,用于未来扩展。
Region
type Region struct{}
说明:Region 是跟踪其执行时间间隔的代码区域。
StartRegion
func StartRegion(ctx context.Context, regionType string) *Region
说明:启动区域并返回它。必须在启动区域的同一 goroutine 中调用返回的 Region 的 End 方法。
使用示例:
package main
import (
"context"
"runtime/trace"
"time"
)
func process(ctx context.Context) {
// 推荐用法
defer trace.StartRegion(ctx, "process").End()
// 处理逻辑
time.Sleep(10 * time.Millisecond)
// 嵌套区域
defer trace.StartRegion(ctx, "subTask").End()
time.Sleep(5 * time.Millisecond)
}
func main() {
ctx := context.Background()
trace.Start(os.Stdout)
defer trace.Stop()
process(ctx)
}
End
func (r *Region) End()
说明:标记跟踪代码区域的结束。
使用示例:参见 StartRegion 示例。
Task
type Task struct{}
说明:Task 是用于跟踪用户定义的逻辑操作的数据类型。
NewTask
func NewTask(pctx context.Context, taskType string) (context.Context, *Task)
说明:创建类型为 taskType 的任务实例,并返回它以及携带任务的 Context。
使用示例:
package main
import (
"context"
"runtime/trace"
"time"
)
func handleRequest(ctx context.Context, requestID string) {
ctx, task := trace.NewTask(ctx, "handleRequest")
defer task.End()
trace.Log(ctx, "requestID", requestID)
// 主处理逻辑
trace.WithRegion(ctx, "main", func() {
time.Sleep(10 * time.Millisecond)
})
// 在单独的 goroutine 中继续处理
go func() {
defer task.End()
trace.WithRegion(ctx, "async", func() {
time.Sleep(5 * time.Millisecond)
})
}()
}
func main() {
ctx := context.Background()
trace.Start(os.Stdout)
defer trace.Stop()
handleRequest(ctx, "req-123")
time.Sleep(100 * time.Millisecond)
}
End
func (t *Task) End()
说明:标记 Task 所表示的操作的结束。
使用示例:参见 NewTask 示例。
典型示例
示例 1:Web 服务器跟踪
package main
import (
"fmt"
"net/http"
"os"
"runtime/trace"
"time"
)
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
trace.Logf(ctx, "http", "Handling request: %s %s", r.Method, r.URL.Path)
// 模拟处理
time.Sleep(10 * time.Millisecond)
fmt.Fprintf(w, "Hello, %s!", r.URL.Path)
}
func main() {
// 启用跟踪
f, _ := os.Create("server.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
http.HandleFunc("/", handler)
fmt.Println("Server starting on :8080")
// 运行 10 秒
go func() {
time.Sleep(10 * time.Second)
os.Exit(0)
}()
http.ListenAndServe(":8080", nil)
}
示例 2:数据库操作跟踪
package main
import (
"context"
"database/sql"
"fmt"
"runtime/trace"
"time"
_ "github.com/mattn/go-sqlite3"
)
func queryUsers(ctx context.Context, db *sql.DB) ([]string, error) {
ctx, task := trace.NewTask(ctx, "queryUsers")
defer task.End()
trace.Log(ctx, "query", "SELECT * FROM users")
rows, err := db.QueryContext(ctx, "SELECT name FROM users")
if err != nil {
return nil, err
}
defer rows.Close()
var names []string
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
return nil, err
}
names = append(names, name)
}
trace.Logf(ctx, "result", "Found %d users", len(names))
return names, nil
}
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
// 创建表
db.Exec("CREATE TABLE users (name TEXT)")
db.Exec("INSERT INTO users VALUES ('Alice'), ('Bob')")
// 启用跟踪
f, _ := os.Create("db.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
ctx := context.Background()
names, err := queryUsers(ctx, db)
if err != nil {
panic(err)
}
fmt.Println("Users:", names)
}
示例 3:并发任务跟踪
package main
import (
"context"
"fmt"
"runtime/trace"
"sync"
"time"
)
func worker(ctx context.Context, id int, wg *sync.WaitGroup) {
defer wg.Done()
ctx, task := trace.NewTask(ctx, "worker")
defer task.End()
trace.Logf(ctx, "worker", "Worker %d starting", id)
// 模拟工作
time.Sleep(time.Duration(id+1) * 10 * time.Millisecond)
trace.Logf(ctx, "worker", "Worker %d done", id)
}
func main() {
ctx := context.Background()
// 启用跟踪
f, _ := os.Create("concurrent.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
var wg sync.WaitGroup
// 启动多个 worker
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(ctx, i, &wg)
}
wg.Wait()
fmt.Println("All workers completed")
}
示例 4:管道处理跟踪
package main
import (
"context"
"fmt"
"runtime/trace"
"time"
)
func stage1(ctx context.Context, in <-chan int, out chan<- int) {
ctx, task := trace.NewTask(ctx, "stage1")
defer task.End()
for n := range in {
trace.WithRegion(ctx, "process", func() {
result := n * 2
trace.Logf(ctx, "data", "%d -> %d", n, result)
out <- result
})
}
close(out)
}
func stage2(ctx context.Context, in <-chan int, out chan<- int) {
ctx, task := trace.NewTask(ctx, "stage2")
defer task.End()
for n := range in {
trace.WithRegion(ctx, "process", func() {
result := n + 1
trace.Logf(ctx, "data", "%d -> %d", n, result)
out <- result
})
}
close(out)
}
func main() {
ctx := context.Background()
// 启用跟踪
f, _ := os.Create("pipeline.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
in := make(chan int)
mid := make(chan int)
out := make(chan int)
go stage1(ctx, in, mid)
go stage2(ctx, mid, out)
// 发送数据
go func() {
for i := 0; i < 5; i++ {
in <- i
time.Sleep(10 * time.Millisecond)
}
close(in)
}()
// 接收结果
for result := range out {
fmt.Println("Result:", result)
}
}
示例 5:批处理作业跟踪
package main
import (
"context"
"fmt"
"runtime/trace"
"sync"
"time"
)
type BatchJob struct {
ID string
Items []int
}
func processBatch(ctx context.Context, job BatchJob) {
ctx, task := trace.NewTask(ctx, "processBatch")
defer task.End()
trace.Logf(ctx, "job", "Processing batch %s with %d items", job.ID, len(job.Items))
var wg sync.WaitGroup
results := make(chan int, len(job.Items))
// 并发处理每个项目
for _, item := range job.Items {
wg.Add(1)
go func(item int) {
defer wg.Done()
ctx, itemTask := trace.NewTask(ctx, "processItem")
defer itemTask.End()
// 模拟处理
time.Sleep(5 * time.Millisecond)
result := item * 2
trace.Logf(ctx, "result", "Item %d -> %d", item, result)
results <- result
}(item)
}
// 等待所有项目完成
go func() {
wg.Wait()
close(results)
}()
// 收集结果
var total int
for result := range results {
total += result
}
trace.Logf(ctx, "summary", "Batch %s total: %d", job.ID, total)
}
func main() {
ctx := context.Background()
// 启用跟踪
f, _ := os.Create("batch.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
// 处理多个批次
jobs := []BatchJob{
{ID: "batch-1", Items: []int{1, 2, 3}},
{ID: "batch-2", Items: []int{4, 5, 6}},
{ID: "batch-3", Items: []int{7, 8, 9}},
}
for _, job := range jobs {
processBatch(ctx, job)
}
fmt.Println("All batches processed")
}
示例 6:HTTP 客户端请求跟踪
package main
import (
"context"
"fmt"
"io"
"net/http"
"os"
"runtime/trace"
"time"
)
func httpClientDo(ctx context.Context, url string) (string, error) {
ctx, task := trace.NewTask(ctx, "httpClientDo")
defer task.End()
trace.Logf(ctx, "http", "GET %s", url)
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return "", err
}
client := &http.Client{Timeout: 5 * time.Second}
trace.WithRegion(ctx, "request", func() {
resp, err := client.Do(req)
if err != nil {
trace.Logf(ctx, "error", "Request failed: %v", err)
return
}
defer resp.Body.Close()
trace.Logf(ctx, "response", "Status: %s", resp.Status)
body, _ := io.ReadAll(resp.Body)
trace.Logf(ctx, "body", "Read %d bytes", len(body))
})
return "success", nil
}
func main() {
ctx := context.Background()
// 启用跟踪
f, _ := os.Create("http.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
urls := []string{
"https://httpbin.org/get",
"https://httpbin.org/status/200",
}
for _, url := range urls {
if _, err := httpClientDo(ctx, url); err != nil {
fmt.Printf("Error: %v\n", err)
}
}
}
示例 7:定时任务跟踪
package main
import (
"context"
"fmt"
"runtime/trace"
"time"
)
func scheduledTask(ctx context.Context, name string, interval time.Duration, stop <-chan struct{}) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
ctx, task := trace.NewTask(ctx, name)
trace.WithRegion(ctx, "execution", func() {
trace.Logf(ctx, "tick", "Running %s at %v", name, time.Now())
// 执行任务
time.Sleep(10 * time.Millisecond)
})
task.End()
case <-stop:
trace.Logf(ctx, "stop", "Stopping %s", name)
return
}
}
}
func main() {
ctx := context.Background()
stop := make(chan struct{})
// 启用跟踪
f, _ := os.Create("scheduler.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
// 启动定时任务
go scheduledTask(ctx, "cleanup", 100*time.Millisecond, stop)
go scheduledTask(ctx, "metrics", 150*time.Millisecond, stop)
// 运行 1 秒
time.Sleep(1 * time.Second)
close(stop)
time.Sleep(100 * time.Millisecond)
fmt.Println("Scheduler stopped")
}
示例 8:性能比较跟踪
package main
import (
"fmt"
"os"
"runtime/trace"
"sort"
"time"
)
// 低效版本
func bubbleSort(arr []int) []int {
n := len(arr)
for i := 0; i < n-1; i++ {
for j := 0; j < n-i-1; j++ {
if arr[j] > arr[j+1] {
arr[j], arr[j+1] = arr[j+1], arr[j]
}
}
}
return arr
}
// 高效版本
func quickSort(arr []int) []int {
if len(arr) <= 1 {
return arr
}
pivot := arr[len(arr)/2]
var left, middle, right []int
for _, v := range arr {
switch {
case v < pivot:
left = append(left, v)
case v == pivot:
middle = append(middle, v)
case v > pivot:
right = append(right, v)
}
}
return append(append(quickSort(left), middle...), quickSort(right)...)
}
func benchmark(ctx context.Context, name string, sortFn func([]int) []int) {
ctx, task := trace.NewTask(ctx, "benchmark")
defer task.End()
trace.Log(ctx, "algorithm", name)
// 生成随机数据
data := make([]int, 1000)
for i := range data {
data[i] = (i * 17) % 1000
}
start := time.Now()
sortFn(data)
elapsed := time.Since(start)
trace.Logf(ctx, "result", "%s took %v", name, elapsed)
fmt.Printf("%s: %v\n", name, elapsed)
}
func main() {
ctx := context.Background()
// 启用跟踪
f, _ := os.Create("sort.trace")
defer f.Close()
trace.Start(f)
defer trace.Stop()
// 比较两种排序算法
benchmark(ctx, "bubbleSort", func(arr []int) []int {
arrCopy := make([]int, len(arr))
copy(arrCopy, arr)
return bubbleSort(arrCopy)
})
benchmark(ctx, "quickSort", func(arr []int) []int {
arrCopy := make([]int, len(arr))
copy(arrCopy, arr)
return quickSort(arrCopy)
})
// 与标准库比较
benchmark(ctx, "stdlib", func(arr []int) []int {
arrCopy := make([]int, len(arr))
copy(arrCopy, arr)
sort.Ints(arrCopy)
return arrCopy
})
}
用户注释 API
日志(Log)
用于记录执行过程中的事件。
// 基本日志
trace.Log(ctx, "category", "message")
// 格式化日志
trace.Logf(ctx, "category", "format: %d, %s", num, str)
区域(Region)
用于标记代码执行的时间区间。
// 使用 WithRegion(推荐)
trace.WithRegion(ctx, "regionType", func() {
// 代码
})
// 使用 StartRegion/End
region := trace.StartRegion(ctx, "regionType")
defer region.End()
任务(Task)
用于跟踪逻辑操作,可跨多个 goroutine。
ctx, task := trace.NewTask(ctx, "taskType")
defer task.End()
// 在任务中记录日志
trace.Log(ctx, "key", "value")
// 在任务中创建区域
trace.WithRegion(ctx, "regionType", func() {
// 代码
})
// 在另一个 goroutine 中使用任务
go func() {
defer task.End()
// 处理
}()
最佳实践
1. 始终使用 defer 停止跟踪
// ✅ 推荐
f, _ := os.Create("trace.out")
defer f.Close()
trace.Start(f)
defer trace.Stop()
// ❌ 不推荐
f, _ := os.Create("trace.out")
trace.Start(f)
// 可能忘记 Stop
2. 使用有意义的类别和类型
// ✅ 推荐
trace.Log(ctx, "database", "Query executed")
trace.WithRegion(ctx, "authentication", func() {})
ctx, task := trace.NewTask(ctx, "processOrder")
// ❌ 不推荐
trace.Log(ctx, "", "did something")
trace.WithRegion(ctx, "stuff", func() {})
3. 任务与上下文配合使用
// ✅ 推荐
func handleRequest(ctx context.Context) {
ctx, task := trace.NewTask(ctx, "handleRequest")
defer task.End()
// 传递 ctx 给子函数
process(ctx)
}
// ❌ 不推荐
func handleRequest(ctx context.Context) {
ctx, task := trace.NewTask(ctx, "handleRequest")
defer task.End()
// 不传递 ctx
process(context.Background())
}
4. 区域应该嵌套
// ✅ 推荐
trace.WithRegion(ctx, "outer", func() {
trace.WithRegion(ctx, "inner", func() {
// 代码
})
})
// ❌ 不推荐:区域交叉
trace.WithRegion(ctx, "outer", func() {
go func() {
trace.WithRegion(ctx, "inner", func() {})
}()
})
5. 生产环境谨慎使用
// ✅ 推荐:通过 flag 控制
var tracing = flag.Bool("trace", false, "enable tracing")
if *tracing {
f, _ := os.Create("trace.out")
defer f.Close()
trace.Start(f)
defer trace.Stop()
}
与其他包配合
net/http/pprof
package main
import (
_ "net/http/pprof"
"net/http"
)
func main() {
// 提供 /debug/pprof/trace 端点
http.ListenAndServe("localhost:6060", nil)
}
testing
package mypkg
import "testing"
func TestSomething(b *testing.B) {
// 使用 go test -trace=trace.out
for i := 0; i < b.N; i++ {
// 测试代码
}
}
context
package main
import (
"context"
"runtime/trace"
)
func main() {
ctx := context.Background()
// 添加超时
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// 使用任务
ctx, task := trace.NewTask(ctx, "timedTask")
defer task.End()
// 执行
doWork(ctx)
}
快速参考
函数
| 函数 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| IsEnabled | - | bool | 检查是否启用跟踪 |
| Log | ctx, category, message | - | 记录日志 |
| Logf | ctx, category, format, args | - | 格式化日志 |
| Start | w io.Writer | error | 开始跟踪 |
| Stop | - | - | 停止跟踪 |
| WithRegion | ctx, regionType, fn | - | 执行区域代码 |
类型
| 类型 | 说明 |
|---|---|
| FlightRecorder | 飞行记录器 |
| FlightRecorderConfig | 飞行记录器配置 |
| Region | 代码区域 |
| Task | 逻辑任务 |
FlightRecorder 方法
| 方法 | 返回值 | 说明 |
|---|---|---|
| NewFlightRecorder | *FlightRecorder | 创建记录器 |
| Enabled | bool | 检查是否活动 |
| Start | error | 开始记录 |
| Stop | - | 停止记录 |
| WriteTo | int64, error | 写入快照 |
Region 方法
| 方法 | 返回值 | 说明 |
|---|---|---|
| StartRegion | *Region | 开始区域 |
| End | - | 结束区域 |
Task 方法
| 方法 | 返回值 | 说明 |
|---|---|---|
| NewTask | Context, *Task | 创建任务 |
| End | - | 结束任务 |
注意事项
1. 性能开销
- 跟踪会影响程序性能
- 避免在生产环境长时间启用
- 使用采样或条件启用
2. 文件大小
- 跟踪文件可能很大
- 及时停止跟踪
- 考虑使用 FlightRecorder 获取窗口快照
3. 上下文传递
- 确保正确传递 context
- 任务依赖上下文传播
- 避免丢失上下文
4. 区域嵌套
- 区域必须在同一 goroutine 中开始和结束
- 区域应该正确嵌套
- 使用 defer 确保结束
5. 工具兼容性
- 使用
go tool trace分析 - 确保 Go 版本兼容
- 跟踪格式可能随版本变化
总结
runtime/trace 包提供了 Go 程序执行跟踪的完整工具集。
核心要点:
- 使用 Start/Stop 启用和停止跟踪
- 使用 Log/WithRegion/NewTask 添加用户注释
- 任务可以跨 goroutine 跟踪逻辑操作
- 区域用于标记代码执行区间
- 使用
go tool trace分析和可视化
主要用途:
- 性能分析和瓶颈识别
- Goroutine 调度分析
- GC 行为观察
- 并发问题调试
- 延迟分布分析
工具链:
# 生成跟踪
go test -trace=trace.out
go run main.go > trace.out
# 分析跟踪
go tool trace trace.out
# Web 界面
go tool pprof -http=:8080 trace.out
与 pprof 的区别:
- pprof - 性能分析(CPU、内存等)
- trace - 执行跟踪(事件、时间线)
- 两者配合使用效果更佳