最近在作文本处理的时候遇到一个很奇怪的现象。串行执行脚本可能只须要几秒钟,可是若是想给每行开个协程并发处理的话,执行时间却从几十秒到几十分钟不等,关键是执行的过程当中cpu的占用并不高。通过一系列的分析以后确认是gc致使的。因此想讲一下排查gc问题的一些小技巧,以后也会给出一些case:浏览器
设置gctrace的变量值为1便可,这个既能够设置成环境变量,也能够选择按以下方式执行:bash
GODEBUG=gctrace=1 go run main.go //GODEBUG=gctrace=1 ./main
GODEBUG=gctrace=1 表明只针对这个进程开启gc追踪功能。程序输出以下:并发
对于上面每一行每一列的具体含义:函数
gc 1 @0.038s 1%: 0.55+0.12+0.081 ms clock, 2.2+0/0.42/1.1+0.32 ms cpu, 4->4->0 MB, 5 MB goal, 4 P。 1 表示第一次执行 @0.038s 表示程序执行的总时间 1% 垃圾回收时间占用总的运行时间百分比 0.018+1.3+0.076 ms clock 垃圾回收的时间,分别为STW(stop-the-world)清扫的时间, 并发标记和扫描的时间,STW标记的时间 0.054+0.35/1.0/3.0+0.23 ms cpu 垃圾回收占用cpu时间 4->4->3 MB 堆的大小,gc后堆的大小,存活堆的大小 5 MB goal 总体堆的大小 4 P 使用的处理器数量
打开了GCTRACE以后对于gc执行的时间点、执行次数以及耗时可能已经有了初步的了解,可是对什么地方耗用大量内存并形成大量延迟可能并不清除。工具
这一点主要使用pprof来实现。开启pprof也特别简单,用net/http/pprof包能够快速实现。只须要在以前的代码中加下面三行就能够:spa
import ( "net/http" _ "net/http/pprof" ) go func() { log.Println(http.ListenAndServe("localhost:8081", nil)) }()
在程序启动以后,只须要在命令行或者浏览器输入如下命令便可:命令行
go tool pprof http://127.0.0.1:8081/debug/pprof/heap //查看堆的使用,即内存使用状况 go tool pprof http://127.0.0.1:8081/debug/pprof/profile //查看cpu耗时,会详细列出每一个函数的耗时 go tool pprof http://127.0.0.1:8081/debug/pprof/goroutine //当前在运行的goroutine状况以及总数
能够看下profile的输出信息, flat表明单个函数的运行时间,而cum则是累加的时间,也会包括这个函数下面的子函数的累加时间,因此main.main确定是100%:debug
若是想看具体的图示的话,可使用png命令将结果存成图片看,好比:code
能够看下生成图片的样子, 有具体的箭头以及每一个函数占用的时间或者内存:协程
基本目前笔者用到的工具就这两个了,感受有收获的读者能够本身实验一下。接下来,我会不按期的分享一些遇到的GC问题的case,欢迎一块儿交流哈。