GODEBUG
支持如下的选项,还有一个memprofilerate
var dbgvars = []dbgVar{
{"allocfreetrace", &debug.allocfreetrace},
{"clobberfree", &debug.clobberfree},
{"cgocheck", &debug.cgocheck},
{"efence", &debug.efence},
{"gccheckmark", &debug.gccheckmark},
{"gcpacertrace", &debug.gcpacertrace},
{"gcshrinkstackoff", &debug.gcshrinkstackoff},
{"gcstoptheworld", &debug.gcstoptheworld},
{"gctrace", &debug.gctrace},
{"invalidptr", &debug.invalidptr},
{"madvdontneed", &debug.madvdontneed},
{"sbrk", &debug.sbrk},
{"scavtrace", &debug.scavtrace},
{"scheddetail", &debug.scheddetail},
{"schedtrace", &debug.schedtrace},
{"tracebackancestors", &debug.tracebackancestors},
{"asyncpreemptoff", &debug.asyncpreemptoff},
{"inittrace", &debug.inittrace},
}
较常用的是gctrace
用来打印GC信息
可以通过 export GODEBUG=gctrace=1 && ./demo
或者 GODEBUG=gctrace=1 ./demo
来开启GODEBUG
选项来运行程序
GODEBUG
还支持两个选项组合使用,比如说可以使用如下的方式开启gc打印和关闭异步抢占
GODEBUG=gctrace=1,asyncpreemptoff=1
何时解析
在程序启动时,调用到schedinit
函数时
// The bootstrap sequence is:
//
// call osinit
// call schedinit
// make & queue new G
// call runtime·mstart
//
// The new G calls runtime·main.
func schedinit() {
……
goargs()
goenvs()
parsedebugvars() // 在这个函数中进行解析
……
}
如何解析
其实就是在对字符串的基本操作
func parsedebugvars() {
// 有一些默认开启的参数
debug.cgocheck = 1
debug.invalidptr = 1
// 获取GODEBUG环境变量的内容,如果不为空时 进行解析
for p := gogetenv("GODEBUG"); p != ""; {
field := ""
// 先按 , 进行拆分
i := index(p, ",")
if i < 0 {
field, p = p, ""
} else {
// 如果存在 “,” 获取第一个 “,” 前的内容,放置到 field 中
field, p = p[:i], p[i+1:]
}
// 在field 中 按“=” 继续拆分
i = index(field, "=")
if i < 0 {
continue
}
// 获取 “=” 前后的内容,存储到key和value中
key, value := field[:i], field[i+1:]
// Update MemProfileRate directly here since it
// is int, not int32, and should only be updated
// if specified in GODEBUG.
// 对于 memprofilerate 特殊处理,设置memprofile的采样频率
if key == "memprofilerate" {
if n, ok := atoi(value); ok {
MemProfileRate = n
}
} else {
// 查找预定义的dbgvars中的内容,找到name与key值相同时,设置其对应的value
for _, v := range dbgvars {
if v.name == key {
if n, ok := atoi32(value); ok {
*v.value = n
}
}
}
}
}
setTraceback(gogetenv("GOTRACEBACK"))
traceback_env = traceback_cache
}
所以只有在dbgvars
中预定义的参数才可以正确解析
解析GODEBUG=gctrace=1
后,在runtime代码中,对于if debug.gctrace > 0
的代码,即可满足这个检查条件,进而进行打印gc信息
如何添加自定义配置选项
当然需要重新编译Go
如何从源码编译安装Go,官方教程
- Go从1.5开始已经实现自举,先从官方下载一份已经编译好的二进制发行版
- 解压,并将该路径设置为
GOROOT_BOOTSTRAP
- 从git仓库克隆go源码,并将该路径设置为
GOROOT
- git checkout 到想要的branch或者tag
cd $GOROOT/src && ./make.bash
go version
进行验证版本号
// $GOROOT\src\runtime\runtime1.go
var debug struct {
asyncpreemptoff int32
gocustom int32
}
var dbgvars = []dbgVar{
{"asyncpreemptoff", &debug.asyncpreemptoff},
{"gocustom", &debug.gocustom},
}
// $GOROOT\src\runtime\proc.go
// The main goroutine.
func main() {
fn := main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime
if debug.gocustom >0 {
println("Hello LeonardWang")
}
// 执行用户main函数
fn()
}
效果如下,当设置了GODEBUG=gocustom=1
时,会先打印 Hello LeonardWang
> cat main.go
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
> go build -o main ./main.go
> ./main
Hello World
> GODEBUG=gocustom=1 ./main
Hello LeonardWang
Hello World
添加自定义的GODEBUG
选项可以在runtime中记录关心的统计信息,在适当的时机进行输出分析。
本文由 LeonardWang 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: May 12,2021