环境变量GOGC设置最初的垃圾收集目标百分比。当新申请的数据和前次垃圾收集剩下的存活数据的比率达到该百分比时,就会触发垃圾收集。默认GOGC=100。设置GOGC=off 会完全关闭垃圾收集。runtime/debug包的SetGCPercent函数允许在运行时修改该百分比。参见http://golang.org/pkg/runtime/debug/#SetGCPercent
环境变量GODEBUG控制运行时的debug输出。GODEBUG的值是逗号分隔的name=val对。支持的name如下:
allocfreetrace: 设置其为1,会导致每次分配都会被记录剖面,会记录每一个对象的分配、释放
及其堆栈踪迹。
efence: 设置其为1,会导致分配器运行模式为:每个对象申请在独立的页和地址,且永不循环利用。
gctrace: 设置其为1,会导致垃圾收集器每次收集都向标准错误输出写入单行的数据,概述收集的总
内存的大小和暂停的总时间长度。设置其为2,会写入同样的概述,但也会写入每次收集的两个数据。
gcdead: 设置其为1,会导致垃圾收集器摧毁任何它认为已经死掉的执行堆栈。
schedtrace: 设置其为X,会导致调度程序每隔X毫秒输出单行信息到标准错误输出,概述调度状态。
scheddetail: 设置schedtrace为X并设置其为1,会导致调度程序每隔X毫秒输出详细的多行信息,
描述调度、进程、线程和go程的状态。
GODEBUG 变量可以控制运行时内的调试变量
- schedtrace:设置
schedtrace=X
参数可以使运行时在每 X 毫秒发出一行调度器的摘要信息到标准 err 输出中。 - scheddetail:设置
schedtrace=X
和scheddetail=1
可以使运行时在每 X 毫秒发出一次详细的多行信息,信息内容主要包括调度程序、处理器、OS 线程 和 Goroutine 的状态。
schedtrace演示
package main
import "sync"
func main() {
wg := sync.WaitGroup{}
for i := 0; i < 100000000; i++ {
wg.Add(1)
go func(wg *sync.WaitGroup) {
var counter int
for i := 0; i < 100; i++ {
counter++
}
wg.Done()
}(&wg)
}
wg.Wait()
}
win下设置临时环境变量:set GODEBUG=schedtrace=1000
- sched:每一行都代表调度器的调试信息,后面提示的毫秒数表示启动到现在的运行时间,输出的时间间隔受
schedtrace
的值影响。 - gomaxprocs:当前的 CPU 核心数(GOMAXPROCS 的当前值)。
- idleprocs:空闲的处理器数量,后面的数字表示当前的空闲数量。
- threads:OS 线程数量,后面的数字表示当前正在运行的线程数量。
- spinningthreads:自旋状态的 OS 线程数量。
- idlethreads:空闲的线程数量。
- runqueue:全局队列中中的 Goroutine 数量,而后面的 [128 0 0 0 0 0 0 0] 则分别代表这 8 个 P 的本地队列正在运行的 Goroutine 数量。
在上面我们有提到 “自旋线程” 这个概念,如果你之前没有了解过相关概念,一听 “自旋” 肯定会比较懵,我们引用 《Head First of Golang Scheduler》 的内容来说明:
自旋线程的这个说法,是因为 Go Scheduler 的设计者在考虑了 “OS 的资源利用率” 以及 “频繁的线程
抢占给 OS 带来的负载” 之后,提出了 “Spinning Thread” 的概念。也就是当 “自旋线程” 没有找到可
供其调度执行的 Goroutine 时,并不会销毁该线程 ,而是采取 “自旋” 的操作保存了下来。虽然看起
来这是浪费了一些资源,但是考虑一下 syscall 的情景就可以知道,比起 “自旋",
线程间频繁的抢占以及频繁的创建和销毁操作可能带来的危害会更大。
scheddetail演示
win下设置临时环境变量:set GODEBUG=scheddetail=1,schedtrace=1000
G
- status:G 的运行状态。
- m:隶属哪一个 M。
- lockedm:是否有锁定 M。
运行时阻塞的详情
waitReasonZero // ""
waitReasonGCAssistMarking // "GC assist marking"
waitReasonIOWait // "IO wait"
waitReasonChanReceiveNilChan // "chan receive (nil chan)"
waitReasonChanSendNilChan // "chan send (nil chan)"
waitReasonDumpingHeap // "dumping heap"
waitReasonGarbageCollection // "garbage collection"
waitReasonGarbageCollectionScan // "garbage collection scan"
waitReasonPanicWait // "panicwait"
waitReasonSelect // "select"
waitReasonSelectNoCases // "select (no cases)"
waitReasonGCAssistWait // "GC assist wait"
waitReasonGCSweepWait // "GC sweep wait"
waitReasonChanReceive // "chan receive"
waitReasonChanSend // "chan send"
waitReasonFinalizerWait // "finalizer wait"
waitReasonForceGGIdle // "force gc (idle)"
waitReasonSemacquire // "semacquire"
waitReasonSleep // "sleep"
waitReasonSyncCondWait // "sync.Cond.Wait"
waitReasonTimerGoroutineIdle // "timer goroutine (idle)"
waitReasonTraceReaderBlocked // "trace reader (blocked)"
waitReasonWaitForGCCycle // "wait for GC cycle"
waitReasonGCWorkerIdle // "GC worker (idle)"
M
- p:隶属哪一个 P。
- curg:当前正在使用哪个 G。
- runqsize:运行队列中的 G 数量。
- gfreecnt:可用的G(状态为 Gdead)。
- mallocing:是否正在分配内存。
- throwing:是否抛出异常。
preemptoff:不等于空字符串的话,保持 curg 在这个 m 上运行。
P
status:P 的运行状态。
- schedtick:P 的调度次数。
- syscalltick:P 的系统调用次数。
- m:隶属哪一个 M。
- runqsize:运行队列中的 G 数量。
- gfreecnt:可用的G(状态为 Gdead)。
gctrace演示
win下设置临时环境变量:set GODEBUG=gctrace=1
官方runtime说明
gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
error at each collection,summarizing the amount of memory collected and the
length of the pause. Setting gctrace=2 emits the same summary but also
repeats each collection. The format of this line is subject to change.
Currently,it is:
gc # @#s #%: #+#+# ms clock,#+#/#/#+# ms cpu,#->#-># MB,# MB goal,# P
where the fields are as follows:
gc # the GC number,incremented at each GC
@#s time in seconds since program start
#% percentage of time spent in GC since program start
#+...+# wall-clock/CPU times for the phases of the GC
#->#-># MB heap size at GC start,at GC end,and live heap
# MB goal goal heap size
# P number of processors used
The phases are stop-the-world (STW) sweep termination,concurrent
mark and scan,and STW mark termination. The CPU times
for mark/scan are broken down in to assist time (GC performed in
line with allocation),background GC time,and idle GC time.
If the line ends with "(forced)",this GC was forced by a
runtime.GC() call and all phases are STW.
Setting gctrace to any value > 0 also causes the garbage collector
to emit a summary when memory is released back to the system.
This process of returning memory to the system is called scavenging.
The format of this summary is subject to change.
Currently it is:
scvg#: # MB released printed only if non-zero
scvg#: inuse: # idle: # sys: # released: # consumed: # (MB)
where the fields are as follows:
scvg# the scavenge cycle number,incremented at each scavenge
inuse: # MB used or partially used spans
idle: # MB spans pending scavenging
sys: # MB mapped from the system
released: # MB released to the system
consumed: # MB allocated from the system
垃圾回收信息
gc 1 @0.141s 0%: 0+1.0+0 ms clock, 0+1.0/1.0/0+0 ms cpu, 4->4->0 MB, 5 MB goal, 8 P
- 1:表示第一次执行
- @0.141s:表示程序开始执行到现在的总时间
- 0%:垃圾回收时间占用的百分比
- 0+1.0+0 ms clock:垃圾回收的时间,分别为STW(stop-the-world)清扫的时间, 并发标记和扫描的时间,STW标记的时间
- 0+1.0/1.0/0+0 ms cpu :垃圾回收占用cpu时间
- 4->4->0 MB :堆的大小,gc后堆的大小,存活堆的大小
- 5 MB :整体堆的大小
- 8 P :处理器数量
系统内存回收信息
scvg: 0 MB released 向操作系统归还了0 MB 内存
scvg: inuse: 1, idle: 5, sys: 7, released: 3, consumed: 4 (MB)
- inuse:已经分配给用户代码、正在使用的总内存大小 (MB)
- idle:空闲以及等待归还给操作系统的总内存大小(MB)
- sys:系统映射的内存
- releasef:释放的系统内存
- consumed:申请的系统内存