goroutine内存泄露

  • 首先看一个示例:
import(
    "_net/http/pprof"
    "sync"
)
var wg sync.WaitGroup
func main() {
    go func() {
        http.ListenAndServe("127.0.0.1:8090", nil)  
    }()

    c := make(chan struct{})
    wg.Add(1)
    for i:=0;i<10000;i++{
        go leak(c)
        wg.Done()
    }
    fmt.Println("xxxx结束!",len(a))
    wg.Wait()
}
func leak(c chan struct{}){
    a := make([]int64,0)
    for i := 0; i < 10000; i++ {
        a = append(a, rand.Int63())
    }
    <-c
}
  • 1 win10系统安装graphviz这个的MSI包,下载地址:(https://graphviz.gitlab.io/_pages/Download/windows/graphviz-2.38.msi),配置好环境变量后启动程序就能在浏览器打开下面的页面,程序绑定了localhost地址:(http://127.0.0.1:8090/debug/pprof/)
  • 2 上面程序是通过结构体阻塞了程序,开启了10000个协程,GC没有回收,导致内存一直占用,通过Go内置包pprof可以看到,有开启了10004个协程,堆区分配了19次内存。这很明显GC没有回收掉这部分的协程内存,


    image.png
  • 3 下面把程序改动下,看内存回收情况
var wg sync.WaitGroup
func main() {
    go func() {
        http.ListenAndServe("127.0.0.1:8090", nil)  
    }()

    wg.Add(1)
    for i:=0;i<10000;i++{
        go leak()
    }
    wg.Wait()
}
func leak(){
    a := make([]int64,0)
    for i := 0; i < 10000; i++ {
        a = append(a, rand.Int63())
    }
    time.Sleep(time.Second * 1)
}
image.png
  • 4 程序没有结束一直占着内存,但是goroutine却大幅下降了,runtime已经回收掉部分内存了,只是程序还有点问题没有结束,改下。测试程序的时候通过检测goroutine可以验证是否有内存泄露问题存在。再CMD下输入:go tool pprof -http :8081 把http://127.0.0.1:8090/debug/pprof/heap 在浏览器输入能更直观的看到程序占用资源的情况分布。
    image.png

你可能感兴趣的:(goroutine内存泄露)