go tool trace 生成的 trace 文件需通过 go tool trace -http=:8080 trace.out 启动 HTTP 服务访问,不可双击或用 file:// 打开;trace.out 必须由 runtime/trace 生成,且 Start/Stop 范围要适中,避免过早结束、defer 中未关闭 stdout 或覆盖 GC STW 阶段。

go tool trace 生成的 trace 文件为什么打不开?
常见错误是直接双击 trace 文件,或者用浏览器打开本地 file:// 路径 —— 这会触发跨域限制,页面白屏或报 Failed to load trace: CORS error。正确做法必须通过 go tool trace 自带的 HTTP 服务启动。
- 先运行
go tool trace -http=:8080 trace.out(端口可换),再访问http://localhost:8080 -
trace.out必须是 Go 程序用runtime/trace启用后生成的二进制格式,不是文本日志 - 若提示
no trace events found,大概率是程序没真正执行到 trace.Start() 后的逻辑,或提前调用了 trace.Stop()
trace.Start() 和 trace.Stop() 的调用时机很关键
延迟分析依赖的是 Goroutine 调度事件的连续采样,不是“拍快照”。如果 Start/Stop 包裹范围太小(比如只包一个函数),几乎看不到调度行为;如果太长(比如整个 main 函数),文件巨大且干扰多。
- 推荐在明确要观测的业务段前后调用:比如 HTTP handler 入口/出口、数据库查询前后
- 务必确保
trace.Start()在main()或 goroutine 启动后尽早调用,否则早期调度事件丢失 - 别在 defer 中写
trace.Stop()而不加os.Stdout关闭 —— trace 会写入 stdout,不关会导致程序 hang 住
看懂 Goroutine 调度延迟,重点盯这三个视图
Trace UI 里真正反映调度延迟的是 Goroutines、Network blocking profile 和 Scheduler latency 三个面板,不是顶部的火焰图。
-
Goroutines视图中,灰色竖条是 Goroutine 处于Runnable状态但未被调度的时间 —— 这就是调度延迟本身,越长越可疑 -
Scheduler latency面板显示每个 P 的调度延迟分布,若某 P 持续 >1ms,可能有锁竞争或 GC 停顿影响 - 注意区分
Running(真正在 CPU 上跑)和Runnable(就绪但没轮到),后者才是调度器的问题,前者可能是 CPU 密集或系统负载高
trace 数据采集本身会影响调度延迟测量
开启 trace 会带来可观测开销:每个 Goroutine 状态切换、系统调用进出都会插入 trace 事件,这会轻微拖慢调度器,尤其在高频 goroutine 创建/销毁场景下。
立即学习“go语言免费学习笔记(深入)”;
- 生产环境慎用全量 trace,建议用
runtime/trace的采样控制(如只对特定路径开启) - 短时压测可用,但不要拿 trace 数据直接对标非 trace 下的 P99 延迟值
- Go 1.21+ 支持
trace.WithFilter,能过滤掉低价值事件(如频繁的 timer 通知),减小体积和干扰
Runnable 时间会被拉长,但这不是调度器问题,而是 GC 强制暂停。得结合 GC 面板一起看。










