Go Trace中“GC Pause”的含义及用户Goroutine暂停疑问
关于Go Trace中“GC Pause”列的疑问解答
问题描述
我用Go trace追踪函数执行时间,程序里创建了大量对象,疑惑GC暂停时间是不是太长。查看源码发现,“GC Pause”列用的是GCTime字段,对应GCDone事件,但GCSTW、GCSweep是独立事件,看起来GCTime是总GC时间而非STW(暂停)时间。想请教:“GC Pause”列具体指什么?这段时间内用户goroutine会被暂停吗?
相关源码分析
cmd/trace/goroutines.go#L298
<table class="details"> <tr> <th onclick="reloadTable('sortby', 'SweepTime')" class="sweep-time"> GC sweeping</th> <th onclick="reloadTable('sortby', 'GCTime')" class="pause-time"> GC pause</th> </tr> {{range .GList}} <tr> <td> {{prettyDuration .SweepTime}} {{percent .SweepTime .TotalTime}}</td> <td> {{prettyDuration .GCTime}} {{percent .GCTime .TotalTime}}</td> </tr> {{end}} </table>
internal/trace/goroutines.go#L275
const ( EvGCStart = 7 // GC start [timestamp, seq, stack id] EvGCDone = 8 // GC done [timestamp] EvSTWStart = 9 // GC mark termination start [timestamp, kind] EvSTWDone = 10 // GC mark termination done [timestamp] EvGCSweepStart = 11 // GC sweep start [timestamp, stack id] EvGCSweepDone = 12 // GC sweep done [timestamp, swept, reclaimed] ) func GoroutineStats() { // ... case EvGCStart: gcStartTime = ev.Ts case EvGCDone: for _, g := range gs { if g.EndTime != 0 { continue } if gcStartTime < g.CreationTime { g.GCTime += ev.Ts - g.CreationTime } else { g.GCTime += ev.Ts - gcStartTime } } gcStartTime = 0 // indicates gc is inactive. }
测试环境与命令
$ go version go version go1.21.0 darwin/amd64 $ go test -bench=BenchmarkGoTrace -benchtime=1000x -run=NONE -trace=trace.out cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz BenchmarkGoTrace-8 1000 22500692 ns/op $ go tool trace trace.out
解答
“GC Pause”列的实际含义
从源码的计算逻辑来看,GCTime统计的是整个GC周期的总时长:从EvGCStart(GC启动)到EvGCDone(GC完全结束)的全部时间,包含了标记阶段(并发执行+短暂STW)、清扫阶段(大部分并发执行)的所有耗时。这个列名存在一定误导性,它并非指用户goroutine被暂停的STW时间。用户goroutine的暂停情况
Go的GC是并发设计,整个GC周期内只有两个短暂的STW(Stop The World)阶段会暂停所有用户goroutine:- GC启动初期的栈扫描准备阶段
- 标记终止阶段(确保标记结果的一致性)
而GCTime包含的大部分时间里,用户goroutine都可以正常运行,不会被暂停。
内容的提问来源于stack exchange,提问作者F566
相关产品推荐
相关产品推荐

