GO: 标准库 runtime
1 · runtime#
go doc runtime
runtime 包是go程序与运行时进行交互的包,提供:控制goroutine,管理内存,控制线程,分析性能,栈回溯等能力;
1.1 · 函数
调度相关:
runtime.Gosched() // 主动让出cpu
runtime.Goexit() // 终止,但defer会运行
runtime.LockOSThread()
runtime.UnlockOSThread()
垃圾回收相关:
runtime.GC() // 手动触发GC,会阻塞
runtime.KeepAlive(any) // 参数在当前调用点之前,都不能被 GC 回收
// 对象不可达 → GC发现 → 执行cleanup/finalizer函数
runtime.SetFinalizer(obj any, finalizer any)
runtime.AddCleanup(ptr *T, cleanup func(S), arg S)
runtime.ReadMemStats(*runtime.MemStats) // 读取分配信息:字节数、对象数
调用栈相关:
runtime.Caller(skip int) // 某一层帧
runtime.Callers(skip int, pc []uintptr) // 收集多层帧的pc地址
runtime.CallersFrames(callers []uintptr) // pc 返回可读栈帧信息
runtime.FuncForPC(pc uintptr) // pc地址获取func信息
runtime.Stack(buf []byte, all bool) // 一步到位,文本栈信息
性能诊断相关:常用go doc runtime/pprof,
// 阻塞
runtime.BlockProfile(p []runtime.BlockProfileRecord)
runtime.SetBlockProfileRate(rate int)
// 锁竞争
runtime.MutexProfile(p []runtime.BlockProfileRecord)
runtime.SetMutexProfileFraction(rate int)
// CPU 采样
runtime.SetCPUProfileRate(hz int)
runtime.GoroutineProfile(p []runtime.StackRecord)
runtime.ThreadCreateProfile(p []runtime.StackRecord)
// 内存
runtime.MemProfile(p []runtime.MemProfileRecord, inuseZero bool)
trace相关,比较底层;常用go doc runtime/trace,
runtime.StartTrace()
runtime.ReadTrace()
runtime.StopTrace()
1.2 · 环境变量
控制Go程序的运行时行为
1.2.1 · GOGC#
设置垃圾收集目标百分比,新分配的数据大小与当前存活的数据大小之比超过此百分比,则触发一次回收。默认GOGC=100。
- 控制 GC 触发频率。
- 默认 100,值越小越频繁 GC,越省内存但可能更慢。
- off 表示关闭 GC。
// 支持在运行时修改
// go doc runtime/debug.SetGCPercent
func SetGCPercent(percent int) int
1.2.2 · GOMEMLIMIT#
内存上限,防止进程吃太多内存
1.2.3 · GOMAXPROCS#
限制了可以在用户层GO代码可以同时执行的操作系统线程的数量;
- 限制同时执行 Go 代码的 OS 线程数。
- 一般默认等于 CPU 核数。
// 支持在运行时修改
// go doc runtime.GOMAXPROCS
func GOMAXPROCS(n int) int
1.2.4 · GODEBUG#
逗号分隔开的name=value列表,用于调试运行时的变量;
变量很多,而且会随 Go 版本变化;最稳妥的方式是直接看:
go doc runtime
下面只记常见、排障时最常用的项。
clobberfree=1:对象释放后用坏数据覆盖,帮助排查 use-after-free 一类问题。cgocheck=0|1:控制 cgo 指针检查;1是默认值。checkfinalizers=1:检查 finalizer / cleanup 常见错误。decoratemappings=0|1:Linux 下是否给/proc/self/maps里的匿名映射加上 Go runtime 注释。disablethp=1:Linux 下禁用 heap 的 transparent huge pages 兼容模式。dontfreezetheworld=1:fatal panic / throw 时不强制冻结所有 goroutine,主要用于调度器调试。efence=1:每个对象单独分配页,并且地址不复用。gccheckmark=1:并发标记后再做一次 STW 校验。gcpacertrace=1:输出 GC pacer 内部状态。gcshrinkstackoff=1:禁用栈缩容,goroutine 栈只能增长。gcstoptheworld=1|2:关闭并发 GC;2还会关闭并发 sweep。gctrace=1:输出每次 GC 的摘要。
格式(go1.26):
gc # @#s #%: #+#+# ms clock, #+#/#/#+# ms cpu, #->#-># MB, # MB goal, # MB stacks, # MB globals, # P
-
#->#-># MB:GC 开始、结束、存活堆大小 -
# MB goal:目标堆大小 -
# MB stacks:可扫描栈大小 -
# MB globals:可扫描全局变量大小 -
行尾若有
(forced),表示由runtime.GC()强制触发 -
harddecommit=1:归还给 OS 的内存额外移除保护,常用于排查 scavenger 相关问题。 -
inittrace=1:输出每个包init的耗时与分配信息。
格式:
init # @#ms, # ms clock, # bytes, # allocs
madvdontneed=0|1:控制归还内存给内核时使用MADV_FREE还是MADV_DONTNEED,平台相关。memprofilerate=X:设置runtime.MemProfileRate。profstackdepth=N:设置大多数 pprof profiler 的最大栈深度,默认128。panicnil=1:关闭panic(nil)的运行时错误。invalidptr=0|1:控制 GC / 栈复制时是否检查无效指针,默认1。sbrk=1:用极简分配器替换正常分配器和 GC,只向 OS 申请内存,不回收。scavtrace=1:输出 scavenger 摘要。
格式(go1.26):
scav # KiB work (bg), # KiB work (eager), # KiB now, #% util
scheddetail=1:和schedtrace=X搭配,输出多行详细调度器状态。schedtrace=X:每X毫秒输出一次调度器摘要。tracebackancestors=N:在 traceback 中附加 goroutine 创建祖先栈。tracefpunwindoff=1:让 tracer / block / mutex profiler 回退到 runtime 自己的 unwinder。asyncpreemptoff=1:关闭基于信号的异步抢占。
net、net/http 也定义了自己的 GODEBUG 项;看各自包文档。
1.2.5 · GOTRACEBACK#
- 控制 panic 时栈输出多少。
- 比如只打当前 goroutine,还是所有 goroutine,还是连 runtime 内部帧也打出来。
// 支持在运行时修改
// go doc runtime/debug.SetTraceback
func SetTraceback(level string)