Go的trace不是用于函数耗时分析,而是记录goroutine调度、GC、系统调用等运行时事件;需用os.Create创建文件传给trace.Start,并确保trace.Stop执行,再用go tool trace解析。

Go 的 trace 不是用来查函数耗时的,它记录的是运行时事件(goroutine 调度、GC、系统调用、阻塞等),不是 CPU profile;想看哪段代码吃 CPU,该用 pprof。
怎么生成能被 go tool trace 解析的 trace.out 文件
核心就三件事:显式创建文件、传给 trace.Start、确保 trace.Stop 执行。
-
trace.Start默认只写内存缓冲区,不落盘——必须用os.Create("trace.out")创建文件并传入,不能只写os.Stdout或漏参数 -
trace.Stop()必须在程序真正退出前执行;os.Exit(1)和log.Fatal()会跳过defer,导致文件末尾损坏,go tool trace报EOF或unknown magic number - 程序运行时间太短(比如 time.Sleep(200 * time.Millisecond) 或用
select{}留出采集窗口 - 别在
init函数里调trace.Start——此时 runtime 还没初始化完,会静默失败
go tool trace 打不开或显示 “no trace events” 怎么办
90% 是 trace 文件本身无效,和浏览器无关。先验证文件是否合格:
- 运行
file trace.out,输出必须是Go execution trace;空文件或几十字节说明trace.Stop()没执行 - 大小应 >1KB;若只有几百字节,大概率是程序秒启秒停,或
trace.Start()放得太晚(例如在http.ListenAndServe()之后) - 绝对不要双击打开
.out文件,也不要直接用file://协议访问——Chrome/Safari 会报 CORS error;正确方式是go tool trace -http=:8080 trace.out,再手动访问http://localhost:8080 - Mac 上 Safari 可能因安全策略拒绝加载,换 Chrome 或 Firefox
为什么看不到 “Scheduler latency” 面板
这个面板默认不激活,必须同时满足三个条件才会出现:
立即学习“go语言免费学习笔记(深入)”;
- 启动前设环境变量:
GODEBUG=scheddetail=1,schedtrace=500 -
trace.Start()前调用runtime.SetBlockProfileRate(1)(值非零即可,这是隐藏开关) - 程序中得有真实阻塞行为(如 channel 等待、锁竞争、syscall),否则 runtime 不生成调度细节事件
- 缺任一条件,UI 只显示模糊的 “Proc Status”,不会出现 “Scheduler latency” 标签页
goroutine 显示 “running” 但卡住不动,是 CPU 占满了吗
不是。在 View trace 的 Goroutines 视图里,“running” 状态只是表示 goroutine 当前被调度器选中执行,但它可能正在等系统调用返回(比如 read、accept)、channel 发送/接收、或锁释放——本质是阻塞,不是 CPU 密集。
- 看灰色竖条:那是 goroutine 处于
Runnable状态但未被调度的时间,才是真正的调度延迟;超过 1ms 就值得查 - 切到
Network blocking profile或Synchronization blocking profile,确认是否集中在某个 fd、mutex 或 channel 上 - 对比
Proc states:如果idle时间占比低、runnable高,说明调度器过载,或GOMAXPROCS设置不合理 - 别只盯着 “running” —— 它可能是假象;关键要看
Runnable delay柱状图和各 blocking 子视图
最常被忽略的点:trace 数据本身会影响调度行为,高频 goroutine 创建/销毁场景下,采样开销会轻微拖慢调度器;生产环境慎用全量 trace,短时压测可用,但别拿 trace 下的 P99 延迟直接对标非 trace 场景。


















