GoLang 有很多的 Profile 工具,包括了 CPU、Memory、Blocking 各种 Profiler 实现,也包括了 GC/Scheduler Tracer、Heap Dumper,这些工具大部分提供的是聚合信息,即使 Dump 这种可以查看内存对象的,也很难确定其执行过程。
于是乎,就有了 Trace 实现。
简介
Trace 工作流程非常简单,在标准库以及核心库中会记录 GoLang 运行期间的每个事件,例如内存分配、垃圾收集器、协程切换、调用阻塞等,通常有如下几种方法可以开启:
- 运行
go test
的时候,带上-trace=trace.out
类似参数。 - 从
pprof
中获取实时信息,默认通过import _ "net/http/pprof"
导入。 - 在代码中编码嵌入,可以根据代码自定义。
如下是简单示例。
package main
import (
"context"
"fmt"
"os"
"runtime"
"runtime/trace"
"sync"
)
func main() {
runtime.GOMAXPROCS(4)
f, err := os.Create("trace.out")
if err != nil {
return
}
defer f.Close()
if err := trace.Start(f); err != nil {
return
}
defer trace.Stop()
ctx, task := trace.NewTask(context.Background(), "sum")
defer task.End()
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go func(region string) {
defer wg.Done()
trace.WithRegion(ctx, region, func() {
var sum, k int64
for ; k < 1000000000; k++ {
sum += k
}
fmt.Println(region, sum)
})
}(fmt.Sprintf("region_%02d", i))
}
wg.Wait()
}
然后通过如下命令导出。
$ go run main.go
$ go tool trace trace.out
其它
gotraceui
除了上述的 Trace View 之外,还可以通过 gotraceui 查看执行结果。
参考
- More Powerful Go Execution Traces 对 GoLang 的 Trace 实现不错的介绍,包括了 Reducing Go Execution Tracer Overhead 介绍如何将开销降低到 1~2% 。
- Design Documents GoLang 的相关设计文档,但是只到了 1.5 版本,不过存在上述的 Trace 方案设计。
- An Introduction to go tool trace 很不错的介绍文档。