地 址:联系地址联系地址联系地址
电 话:020-123456789
网址:kkkk.twqueen.com
邮 箱:admin@aa.com
Heap: A sampling of memory allocations of live objects. You can specify the gc GET parameter to run GC before taking the heap sample.
添加gc这个parameter到get的url里 , 可以在采样之前强制执行一次GC后,开源再进行采样;来之pprof.go(net/http/pprof.go)源码
Heap的手工埋点
如果是Run over Once的工具包,需要自己进行手工埋点的实战话, 大致的第章方法和上面CPU Profiling的埋点方式一致 ,只是内存需要调用不同的pprof的方法即可; 对于Heap埋点 ,调用pprof.WriteHeapProfile
if err := pprof.WriteHeapProfile(f1); err != nil { n panic("could not start heap-1 profile: ")n }n
pprof工具Heap分析
运行命令
go tool pprof http://localhost:8999/debug/pprof/heap
使用top命令,查看内存占用最多的爱上地方
Top命令的结果,列表出了在采样的开源快照,发生的门至程序中各种函数调用过程中内存占用最多的函数调用;
其中每一行都表示一个采用到的函数调用,
每类都对应着采集到的实战数据分析; 列的参照如下
flat:函数在调用中内存占用数量
flat%:函数在调用中内存占用的百分比
sum% :所有函数累加使用内存的比例,即所有flat%的第章总和
cum : 函数以及子函数运行所使用内存 ,应该大于等于flat
cum%: 函数以及子函数运行所使用内存的内存比例 ,应该大于等于flat%
函数的分析名字
这里可以看到调用现在内存占用最多的占用内存60MB, 占所有内存总量的99.15% ,main.startHttpServer.func3,爱上 这个函数的调用占用的内存基本上就是所有的内存 , 这个函数究竟做了哪些动作,导致内存的占用, 我们可以在pprof里运行list命令, 进一步进行分析
使用pprof命令:list 函数名。 可以用pprof分析函数中的哪一行导致的内存占用
(pprof) list func3nTotal: 60.52MBnROUTINE ======================== main.startHttpServer.func3 in n E:WORKPROJECTgitgogohutoolboot4go-docker-uidocker.ui.gonn 60MB 60MB (flat, cum) 99.15% of Totaln . . 180:n . . 181: if len(testPool) >= POOLSIZE { n . . 182: testPool = testPool[0:0]n . . 183: }n . . 184:n 60MB 60MB 185: testPool = append(testPool, make([]byte, SIZE))n . . 186:n . . 187: return niln . . 188: })n . . 189:n . . 190: router.Any("/debug/pprof/*", func(ctx *routing.Context) error {
通过这个命令 ,可以直接追击到源代码的行数,从而进行仔细的调用过程分析
代码185行: make([]byte, SIZE) 进行了内存的操作, 这里的60M全部这里进行操作的 。
使用图形化web命令进行分析
在pprof的交互模式里输入web命令
使用tree命令查看
(pprof) treenShowing nodes accounting for 206.50MB, 99.28% of 208MB totalnDropped 15 nodes (cum <= 1.04MB)n----------------------------------------------------------+-------------n flat flat% sum% cum cum% calls calls% + contextn----------------------------------------------------------+-------------n 204MB 100% | github.com/qiangxue/fasthttp-routing.(*Context).Nextn 204MB 98.08% 98.08% 204MB 98.08% | main.startHttpServer.func3n----------------------------------------------------------+-------------n 2.50MB 100% | runtime.newmn 2.50MB 1.20% 99.28% 2.50MB 1.20% | runtime.allocmn----------------------------------------------------------+-------------n 204MB 100% | github.com/qiangxue/fasthttp-routing.(*Router).HandleRequestn 0 0% 99.28% 204MB 98.08% | github.com/qiangxue/fasthttp-routing.(*Context).Nextn 204MB 100% | main.startHttpServer.func3n----------------------------------------------------------+-------------n 204MB 100% | main.startHttpServer.func8n 0 0% 99.28% 204MB 98.08% | github.com/qiangxue/fasthttp-routing.(*Router).HandleRequestn 204MB 100% | github.com/qiangxue/fasthttp-routing.(*Context).Nextn----------------------------------------------------------+-------------n 204MB 100% | github.com/valyala/fasthttp.(*workerPool).workerFuncn 0 0% 99.28% 204MB 98.08% | github.com/valyala/fasthttp.(*Server).serveConnn 204MB 100% | main.startHttpServer.func8n----------------------------------------------------------+-------------n 0 0% 99.28% 204MB 98.08% | github.com/valyala/fasthttp.(*workerPool).getCh.func1n 204MB 100% | github.com/valyala/fasthttp.(*workerPool).workerFuncn----------------------------------------------------------+-------------n 204MB 100% | github.com/valyala/fasthttp.(*workerPool).getCh.func1n 0 0% 99.28% 204MB 98.08% | github.com/valyala/fasthttp.(*workerPool).workerFuncn 204MB 100% | github.com/valyala/fasthttp.(*Server).serveConnn----------------------------------------------------------+-------------n 204MB 100% | github.com/valyala/fasthttp.(*Server).serveConnn 0 0% 99.28% 204MB 98.08% | main.startHttpServer.func8n 204MB 100% | github.com/qiangxue/fasthttp-routing.(*Router).HandleRequestn----------------------------------------------------------+-------------n 0 0% 99.28% 2MB 0.96% | runtime.mstartn 2MB 100% | runtime.mstart0n----------------------------------------------------------+-------------n 2MB 100% | runtime.mstartn 0 0% 99.28% 2MB 0.96% | runtime.mstart0n 2MB 100% | runtime.mstart1n----------------------------------------------------------+-------------n 2MB 100% | runtime.mstart0n 0 0% 99.28% 2MB 0.96% | runtime.mstart1n 2MB 100% | runtime.schedulen----------------------------------------------------------+-------------n 2.50MB 100% | runtime.startmn 0 0% 99.28% 2.50MB 1.20% | runtime.newmn 2.50MB 100% | runtime.allocmn----------------------------------------------------------+-------------n 2.50MB 100% | runtime.schedulen 0 0% 99.28% 2.50MB 1.20% | runtime.resetspinningn 2.50MB 100% | runtime.wakepn----------------------------------------------------------+-------------n 2MB 80.00% | runtime.mstart1n 0 0% 99.28% 2.50MB 1.20% | runtime.schedulen 2.50MB 100% | runtime.resetspinningn----------------------------------------------------------+-------------n 2.50MB 100% | runtime.wakepn 0 0% 99.28% 2.50MB 1.20% | runtime.startmn 2.50MB 100% | runtime.newmn----------------------------------------------------------+-------------n 2.50MB 100% | runtime.resetspinningn 0 0% 99.28% 2.50MB 1.20% | runtime.wakepn 2.50MB 100% | runtime.startmn----------------------------------------------------------+-------------
对比一下func3和func8
(pprof) list func3nTotal: 208MBnROUTINE ======================== main.startHttpServer.func3 nin E:WORKPROJECTgitgogohutoolboot4go-docker-uidocker.ui.gon 204MB 204MB (flat, cum) 98.08% of Totaln . . 180:n . . 181: if len(testPool) >= POOLSIZE { n . . 182: testPool = testPool[0:0]n . . 183: }n . . 184:n 204MB 204MB 185: testPool = append(testPool, make([]byte, SIZE))n . . 186:n . . 187: return niln . . 188: })n . . 189:n . . 190: router.Any("/debug/pprof/*", func(ctx *routing.Context) error {
(pprof) list func8 nTotal: 208MBnROUTINE ======================== main.startHttpServer.func8nin E:WORKPROJECTgitgogohutoolboot4go-docker-uidocker.ui.gon 0 204MB (flat, cum) 98.08% of Totaln . . 248:n . . 249: Logger.Debug("router.HandleRequest is finish")n . . 250:n . . 251: }()n . . 252:n . 204MB 253: router.HandleRequest(ctx)n . . 254: }n . . 255:n . . 256: //go http.ListenAndServe("0.0.0.0:8887", nil)n . . 257:n . . 258: // Start HTTP server.n
heap提供了对内存进行分析的途径 ,通过对内存的占用量的分析 ,我们可以结合着程序的压力测试 ,对程序的内存泄漏进行排查和分析,对内存只增不减的等可疑情况地方,进行排查,最终发现问题
heap的pprof样本中的数据项
通过http://localhost:8999/debug/pprof/可以查看heap的信息
这些信息是样本中的数据项,相对于我们通过web访问时 ,访问当前时间的heap的一个快照; 熟悉这些数据项所表示的含义 ,也非常对我们了解当前程序运行时的内存情况非常有帮助。
这里对应的样本的输出的源代码可以参考net/http/pprof/pprof.go, runtime/pprof/pprof.go和runtime/mstats.go