下载测试代码
go get
中可以获取测试程序, 注意加上 -d
避免下载后自动安装。
Github
go get -d github.com/wolfogre/go-pprof-practice cd $GOPATH/src/github.com/wolfogre/go-pprof-practice
如果 go get 下载不了, 可以 git clone 下载
gir clone https://github.com/wolfogre/go-pprof-practice
对代码进行编译
然后运行
go mod init go mod tidy
最后再运行
go build ./go-pprof-practice
保持程序运行,打开浏览器访问 http://localhost:6060/debug/pprof/
,可以看到如下页面:
内存泄漏问题排查
golang 和 Java 有点类似,自带了内存回收, 所以一般不会发生内存泄漏。但是也不绝对, golang 中 协程本身是可能泄漏的,或者叫做协程协程失控,进而导致内存泄漏。
启动程序
为了能更加图形化的展示,可以安装。graphviz
安装方式
brew install graphviz # for macos apt install graphviz # for ubuntu yum install graphviz # for centos
安装完成后,我们继续在上文的交互式终端里输入 web
,注意,虽然这个命令的名字叫“web”,但它的实际行为是产生一个 .svg
文件,并调用你的系统里设置的默认打开 .svg
的程序打开它。如果你的系统里打开 .svg
的默认程序并不是浏览器(比如可能是你的代码编辑器),这时候你需要设置一下默认使用浏览器打开 .svg
文件
浏览器访问 http://localhost:6060/debug/pprof/
可以看到协程有 46 个, 使用 pprof
排查一下
go tool pprof http://localhost:6060/debug/pprof/goroutine
可以看到 cum 那一行 , 是 Drink 有40 个协程。
查看 list.Drink
输入 web
, 浏览器可以看到 冒红的那部分。
可能这次问题藏得比较隐晦,但仔细观察还是不难发现,问题在于
github.com/wolfogre/go-pprof-practice/animal/canidae/wolf.(*Wolf).Drink 在不停地创建没有实际作用的协程:
func (w *Wolf) Drink() { log.Println(w.Name(), "drink") for i := 0; i < 10; i++ { go func() { time.Sleep(30 * time.Second) }() } }
可以看到 Drink 函数 ,每次循环会有创建10个协程, 协程会 sleep 30s 才会退出,如果反复调用这个 Drink 函数, 那么会导致大量协程出现泄漏,协程数会增加。