什么是pprof

pprof是一个收集profiling数据样本,用于可视化展示和分析程序性能的工具,有cpu、内存、trace、Goroutine等。

go语言的工具包里面的自带pprof;

➜  darwin_amd64 pwd
/usr/local/go1.12.0/pkg/tool/darwin_amd64
➜  darwin_amd64 ll
......
-rwxr-xr-x  1 root  wheel    14M Jul  9 05:30 pprof
➜  ~ go tool pprof --help                                                      
usage:                                                                         
                                                                               
Produce output in the specified format.                                        
                                                                               
   pprof <format> [options] [binary] <source> ...                              
                                                                               
Omit the format to get an interactive shell whose commands can be used         
to generate various views of a profile                                         
                                                                               
   pprof [options] [binary] <source> ...                                       
                                                                               
Omit the format and provide the "-http" flag to get an interactive web
interface at the specified host:port that can be used to navigate through
various views of a profile.

   pprof -http [host]:[port] [options] [binary] <source> ...                                                 

启用

如果想使用http请求访问可以参考官方的说明 overview, 里面讲述了如何使用,并同时给了一些常用的url示意;

go func() {
	log.Println(http.ListenAndServe("localhost:6060", nil))
}()

或者自己写http请求也可以,以下是我在iris里面添加的一些代码;但是未注册的好像请求不了;所以建议还是使用官方推荐的方式

// RegisterPProf pprof相关注册
// 以下url未注册  /debug/pprof/heap、goroutines、
func RegisterPProf(app *iris.Application) {
	app.Get("/debug/pprof/", route.PProfIndexHandle())
	app.Get("/debug/pprof/cmdline", route.PProfCmdlineHandle())
	app.Get("/debug/pprof/profile", route.PProfProfileHandle())
	app.Get("/debug/pprof/symbol", route.PProfSymbolHandle())
	app.Get("/debug/pprof/trace", route.PProfTraceHandle())
}

后来看了一下 评论 是可以实现的; 如果想全量补充,可以使用以下方式:

func RegisterPProf(app *iris.Application) {
	app.Get("/debug/pprof/", route.PProfIndexHandle())
	app.Get("/debug/{code:string}", route.PProfHandle())
}

// PProfHandle
func PProfHandle() context.Handler {
	return hero.Register(func(ctx iris.Context) (code string, _ctx iris.Context) {
		code = ctx.URLParam("code")
		return code, ctx
	}).Handler(func(code string, ctx iris.Context) {
		fmt.Printf("url param code is : %s\n", code)
		switch code {
		case "cmdline":
			pprof.Cmdline(ctx.ResponseWriter(), ctx.Request())
		case "symbol":
			pprof.Symbol(ctx.ResponseWriter(), ctx.Request())
		case "trace":
			pprof.Trace(ctx.ResponseWriter(), ctx.Request())
		case "profile":
			pprof.Profile(ctx.ResponseWriter(), ctx.Request())
		case "allocs":
			pprof.Handler("allocs").ServeHTTP(ctx.ResponseWriter(), ctx.Request())
		case "block":
			pprof.Handler("block").ServeHTTP(ctx.ResponseWriter(), ctx.Request())
		case "goroutine":
			pprof.Handler("goroutine").ServeHTTP(ctx.ResponseWriter(), ctx.Request())
		case "heap":
			pprof.Handler("heap").ServeHTTP(ctx.ResponseWriter(), ctx.Request())
		case "mutex":
			pprof.Handler("mutex").ServeHTTP(ctx.ResponseWriter(), ctx.Request())
		case "threadcreate":
			pprof.Handler("threadcreate").ServeHTTP(ctx.ResponseWriter(), ctx.Request())
		default:
			pprof.Index(ctx.ResponseWriter(), ctx.Request())
		}
	})
}

还有一种方式是使用runtime包进行代码操作;这种方式可以用于非http请求的应用,运行一段时间就结束的那种

f, err := os.Create(*cpuprofile)
...
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
...
f, err := os.Create(*memprofile)
pprof.WriteHeapProfile(f)
f.Close()

使用

由于可视化使用了 Graphviz 来生成关系图和火焰图,所以需要安装一下;

第一种方式:可以将文件下载下来,然后另启一个http端口号

curl -O http://localhost:6060/debug/pprof/heap /Users/admin/projects/go/source/heap
go tool pprof -http=":8080" /Users/admin/projects/go/source/heap

或者直接使用交互模式;可以看到交互模式是先将文件下载下来,然后存放到pprof文件夹下,然后可以使用一些命令和选项进行分析

➜  ~ go tool pprof http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profile in /Users/admin/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz
Type: inuse_space
Time: Aug 31, 2019 at 10:00pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) 

参考: