简介
Go 语言的 runtime/trace 包含一个强大的工具,用于理解和排查 Go 程序。其中的功能允许跟踪每个 goroutine 在一段时间内的执行情况。然后,使用 go tool trace 命令(或优秀的开源工具 gotraceui)可以可视化和探索这些跟踪中的数据。
跟踪的魔力在于,它可以轻松地揭示程序中其他方式难以看到的东西。例如,在 CPU 概要文件中很难看到并发瓶颈,因为没有要采样的执行。但在执行跟踪中,缺乏执行将以惊人的清晰度显示出来,并且被阻塞的 goroutine 的堆栈跟踪将迅速指向罪魁祸首。Go 开发人员甚至可以为自己的程序添加任务、区域和日志,以便将他们更高层次的关注点与更低层次的执行细节相关联。
问题
不幸的是,执行跟踪中的大量信息通常无法获取。历史上,四个主要问题阻碍了跟踪:
- 跟踪的开销很高。
- 跟踪无法很好地扩展,并且可能变得太大而无法分析。
- 经常不清楚何时开始跟踪以捕获特定的错误行为。
- 难以将跟踪数据与程序的源代码相关联。
改进
Go 1.20 和 Go 1.21 中引入了许多改进,以解决这些问题。这些改进包括:
- 更高效的跟踪机制,可降低开销并提高可伸缩性。
- 新的 API,可更轻松地启动和停止跟踪以及控制跟踪的范围。
- 改进的工具,可用于可视化和探索跟踪数据。
- 新的工具,可将跟踪数据与程序的源代码相关联。
结果
这些改进使 Go 执行跟踪成为一种更强大、更易于使用的工具。它们使 Go 开发人员能够更轻松地理解和排查其程序中的并发问题。
示例
以下是一个示例,说明如何使用 Go 1.21 中的新 API 启动跟踪:
Go
代码语言:javascript复制
func main() {
// Start a trace lasting for 1 second.
trace.Start(trace.Options{Duration: time.Second})
// Do some work.
for i := 0; i < 1000000; i {
// ...
}
// Stop the trace.
trace.Stop()
}
然后,可以使用 go tool trace 命令可视化跟踪:
代码语言:javascript复制go tool trace main.trace
结论
Go 执行跟踪是理解和排查 Go 程序中并发问题的强大工具。Go 1.20 和 Go 1.21 中的改进使跟踪更加强大、易于使用。Go 开发人员应该考虑将跟踪作为其工具集的一部分。