go trace 使用
1 Go trace 介绍
go trace 在 go 1.5 版本加入,会在运行中收集以下事件的所有数据
-
创建,启动和终止 goroutine
-
阻塞/非阻塞 goroutines(syscalls, channels, locks)
-
网络 io
-
Syscalls
-
gc
收集后不会做任何类型的聚合和抽样。
pprof 用来分析 CPU 和内存分别用在了哪里,trace 用来确定什么阻止了 goroutine 运行,goroutine 在 OS 线程上如何被调度。
1.1 收集 trace 的方式
有三种收集trace的方法:
**使用 runtime/trace包 **
这个需要调用trace.Start
和trace.Stop
。
f, _ := os.Create("./trace.out")
_ = trace.Start(f)
defer trace.Stop()
**使用 ****-trace=
用来收集关于被测试代码的trace时比较有用。
**使用 debug/pprof/trace handler **
这是用来收集运行中的web应用的trace的最好的方法。
curl localhost:8080/debug/pprof/trace?seconds=10 > trace.out // zsh 可能报错
2 实践
首先从一个简单的程序开始。
package main
import (
"log"
"os"
"runtime/trace"
)
func main() {
f, _ := os.Create("./trace.out")
_ = trace.Start(f)
defer trace.Stop()
const n = 3
leftmost := make(chan int)
right := leftmost
left := leftmost
for i := 0; i < n; i++ {
right = make(chan int)
go pass(left, right)
left = right
}
go sendFirst(right)
log.Println(<-leftmost)
}
func pass(left, right chan int) {
v := 1 + <-right
left <- v
}
func sendFirst(ch chan int) { ch <- 0 }
这份代码通过 channel 创建了一个 goroutine 链。
我们指定了会在当前目录生成 trace 文件。运行代码,然后使用 go tool trace trace.out
它会启动一个 web 服务,127.0.0.1 加上一个随机端口。页面如下
3 View trace
交互式,可视化的显示了这个程序执行的时间轴。这个视图显示了在每个虚拟处理器上运行着什么,以及什么是被阻塞等待运行的。注意这个视图只能在 Chrome 上显示。
3.1 Timeline
Timeline 显示执行的时间,根据跟踪定位的不同,时间单位可能会发生变化。可以用键盘的 WASD 键来导航时间轴。
3.2 STATS
Heap,Goroutine,Threads这里有几行数据,鼠标定位到某一行在数据,在下方就会显示对应的信息
-
Goroutine 行显示有多少 Goroutine 在运行。有多少是可运行(等待被调度)的。大量可运行的 goroutine 说明可能存在调度竞争。
-
Heap 行显示的是执行期间的内存分配,这对于发现内存泄露非常有用。也能检查垃圾回收在每次运行时能够释放多少内存。
-
OS Threads 显示有多少 OS 线程正在被使用,有多少个被 syscall 阻塞。
3.3 Procs
Virtual Processors每个虚拟处理器显示一行。数量即 GOMAXPROCS 环境环境变量控制的。
3.4 Goroutine 和 events
显示在每个虚拟处理器上有什么 goroutine 在运行。连接 goroutine 的连线代表事件,
选择右上角 “View Options -> Flow events” 可以看到 goroutine 之间的连线,这些连线代表事件。
选择一个 goroutine,可以看到这些信息
-
Title 它的名称
-
Start 开始时间
-
Wall Duration 持续时间
-
Start Stack Trace 开始时的栈 trace
-
End Stack Trace 结束时的栈 trace
-
Events 该 goroutine 产生的事件
4 Goroutine analysis
显示了在整个执行过程中,每种类型的 goroutine 是如何创建的。在选择一种类型后就可以看到关于这种类型的 goroutine 信息。比如,视图中 mutex 中获取锁,从网络读取等等。
5 Network/Sync/Syscall blocking profile
这些图显示了 goroutine 在这些资源上所花费的时间。它们非常接近 pprof 上的内存/cpu 分析。是分析锁竞争的最佳选择。
6 Scheduler latency profiler
为调度器级别的信息提供计时功能,显示调度在哪里最耗费时间。
参考
https://mp.weixin.qq.com/s/I9xSMxy32cALSNQAN8wlnQ