使用pprof和Graphviz结合来分析golang程序的性能问题。
golang官方用来做监控分析的库,一般都是pprof,我们这里使用的net/http/pprof可以做到直接看到当前web服务的状态,包括cpu,内存等的使用情况。
Graphviz (英文:Graph Visualization Software的缩写)是一个由AT&T实验室启动的开源工具包,用于绘制DOT语言脚本描述的图形。它也提供了供其它软件使用的函式库。什么是Graphviz
下载graphviz,zip和mis看个人情况,都可以,这边使用的是2.38 Stable Release
的zip,解压后直接使用。
解压或者安装后设置环境变量:
官方提供了一个名为net/http/pprof
的包,用于go程序的性能检测。在这个包中已经实现了已经uri
,加载这个包然后监听一个端口就可以在程序运行的过程中获取到实时的一些信息。官方部分描述文件:
我们可以使用2种方式来查看pprof提供的性能检测数据:
官方的文档中提供了使用命令查看的详细过程。
在应用程序中引入net/http/pprof
包,并且监听一个http端口即可。
import (
"context"
"log"
"net/http"
_ "net/http/pprof"
)
func main() {
addr := "localhost:6060"
go func() {
if err := http.ListenAndServe(addr,nil); err != nil {
panic(err)
}
}()
// TODO
select{}
}
上面代码表示在端口6060上监听了pprof的性能url,通过既定的一些命令可以查看不通的性能数据。
在终端或者浏览器上可以使用命令查看heap profile
、cpu profile
、block profile
、mutex profile
和trace 信息
,部分命令可以增加采集的时间,采集到不同时长的数据。
启动已经增加了net/http/pprof
包的程序,在另一个打开的终端上输入上面的指令,会返回一个pprof的命令行,在这个命令行中通过一个指令就可以查看细节。
heap profile
go tool pprof http://localhost:6060/debug/pprof/heap
cpu profile
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
这句话表示采集时常为30s的cpu信息
block profile
go tool pprof http://localhost:6060/debug/pprof/block
mutex profile
go tool pprof http://localhost:6060/debug/pprof/mutex
trace
wget http://localhost:3030/debug/pprof/trace?seconds=5
trace数据有一些不一样。net/http/pprof
包给trace信息返回的是一个文件,上面命令表示获取5s钟的trace信息。使用浏览器时,直接输入url就可以采集到对应时常的trace信息。
trace文件存下来后,需要用到go tool
的trace
命令来解析,才能像其他的命令一样看到详细的tracec信息。
执行go tool trace trace文件
解析trace文件,之后会有一个端口,在这个端口上查看trace信息。如下如:
我们以cpu profile命令为例说明。启动demo程序后,在另一个终端中输入go tool pprof http://localhost:3030/debug/pprof/profile?seconds=10
后,等待10s钟后,过程如下:
1)采集数据
2)采集完成后
采集完成后可以使用命令查看,详细的命令可以输入help
查看。我们这里以web
命令使用Graphviz
查看图形关系。
3)web产生的图形关系
通过分析web中的图像关系就可以比较详细的看出cpu的使用情况。
直接查看的指令会能够完全提供查看性能数据的需求,但是有一些场景我们需要把一些文件拿下来慢慢分析,这时候将采集到的信息写入文件是必须的。鉴于此,基于go原生的net/http
对net/http/pprof
进行了封装,并提供接口便于控制。
这个封装提供两个接口:初始化pprof包的函数和安全关闭pprof的http函数。对外使用/start
开始采集数据,默认打开关闭gc
;/startnogc
开始采集数据并且关闭了gc
;/stop
停止采集数据。
1)初始化函数Pprof
func Pprof(port int) {
addrs := fmt.Sprintf("localhost:%d", port)
log.Printf("pprof listen addr=[%v]", addrs)
http.HandleFunc("/start", handleStart)
http.HandleFunc("/stop", handleStop)
srv = &http.Server{
Addr: addrs,
Handler: nil,
}
go func(addr string) {
if err := srv.ListenAndServe(); err != nil {
log.Panic(err)
}
}(addrs)
}
2)关闭http-srv句柄函数Shutdown
func Shutdown() error {
ctx, cancle := context.WithTimeout(context.Background(), time.Duration(1))
defer cancle()
if err := srv.Shutdown(ctx); err != nil {
log.Printf("stop srv failed,%v", err)
return err
}
return nil
}
使用时先初始化,当程序退出时需要调用Shutdown
释放资源。
func main() {
logger = log.New(os.Stdout, "", log.Lshortfile|log.Ldate|log.Ltime)
pprof.Pprof(3030)
logger.Printf("++++++++")
result1 := gen(1, 100000000)
result2 := gen(2, 20000000)
for range merge(result1, result2) {
_count++
}
HandlerExit(func(s os.Signal) int {
logger.Printf("receive get a signal %s", s.String())
if err := pprof.Shutdown(); err != nil {
logger.Printf(" service exit, error: %s", err)
return 1
}
logger.Printf(" service exit")
return 0
})
}
1)产生的文件
发送/start
或/startgc
后,会在可执行文件的目录下产生一个名为pprof
的目录,存在4个文件。
2)查看block
、mem
和cpu
对于block.pprof
、cpu.pprof
和mem.pprof
文件,查看的指令是一样的。在当前的目录下打开终端,输入go tool pprof 文件名
即可。以cpu为例说明:
(1)使用命令解析cpu.pprof
文件
这里还是以web
命令示范,直接在浏览器查看性关系图
trace.out
的数据内容较多,我们在 golang学习笔记-pprof性能分析2 单独分析