Go使用 pprof 和 dump-goroutine-stacktraces

Gin框架下使用pprof查看程序占cpu资源

代码添加

import "github.com/DeanThompson/ginpprof"
...
router := gin.Default()
ginpprof.Wrap(router)
...

浏览器访问

http://ip:port/debug/pprof/

Go使用 pprof 和 dump-goroutine-stacktraces_第1张图片

  • allocs:对所有过去内存分配的抽样
  • block:导致同步原语阻塞的堆栈跟踪
  • cmdline:当前程序的命令行调用
  • goroutine:当前所有goroutine的堆栈跟踪
  • heap: 堆内存分配情况的记录,默认每分配512K字节时取样一次。
  • mutex:查看争用互斥锁的持有者。
  • profile:CPU配置文件
  • threadcreate:创建新OS线程的堆栈跟踪
  • trace:当前程序的执行轨迹

可读信息太少,下面展示pprof web功能

命令行

//输入
$ go tool pprof http://ip:port/debug/pprof/profile
//输出
Saved profile in C:\Users\seeta\pprof\pprof.main.samples.cpu.008.pb.gz
File: main
Type: cpu
Time: Jun 13, 2019 at 12:04pm (CST)
Duration: 30s, Total samples = 0
No samples were found with the default sample value type.
Try "sample_index" command to analyze different sample values.
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)
//在(pprof)右边输入 web
(pprof) web
//自动打开浏览器

Go使用 pprof 和 dump-goroutine-stacktraces_第2张图片

采样时间

上图展示了30s 的 CPU 采样信息,可使用second指定采样时间,例如命令行输入:

$ go tool pprof http://ip:port/debug/pprof/profile?second=60

采样状态

查看根据历史(-alloc_space)或正在使用(-inuse_space)

$ go tool pprof -alloc_space http://ip:port/debug/pprof/profile?second=60

采样筛选

运行 go tool pprof 命令时加上 –nodefration=0.05 参数,表示如果调用的子函数使用的 CPU、memory 不超过 5%,就忽略它,不要显示在图片中。

火焰图

要生成火焰图,需要事先安装 FlameGraph工具,这个工具的安装很简单,只要把对应的可执行文件放到 $PATH 目录下就行,在window下不可用。

dump-goroutine-stacktraces

重点:

runtime.Stac

参考代码:

func main(){
    ...
    setupSigusr1Trap()
    ...
}
func setupSigusr1Trap() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGUSR1)//监听SIGUSER1信号,仅限linux系统,win下编译出错
	go func() {
		for range c {
			DumpStacks()
		}
	}()
}
func DumpStacks() {
	buf := make([]byte, 16384)
	buf = buf[:runtime.Stack(buf, true)]
	fmt.Printf("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
}

执行代码,命令行输入(linux系统):

$ lsof -i:port //port是程序监听的端口,这样可以获取程序的pid
//COMMAND   PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
// main     123   xxx  ...
$ kill -n USR1 123 
//这个命令并不会杀死进程,只是发送了SIGUSER1信号
//控制台输出如下类似的goroutin效信息
=== BEGIN goroutine stack dump ===
goroutine 36 [running]:
main.DumpStacks()
        /home/seeta/wjx/jiesi_data/main.go:61 +0x77
main.setupSigusr1Trap.func1(0xc0001a62a0)
        /home/seeta/wjx/jiesi_data/main.go:54 +0x34
created by main.setupSigusr1Trap
        /home/seeta/wjx/jiesi_data/main.go:52 +0xab

goroutine 1 [IO wait, 14 minutes]:
internal/poll.runtime_pollWait(0x7fb675e01f00, 0x72, 0x0)
        /usr/local/go/src/runtime/netpoll.go:173 +0x66
internal/poll.(*pollDesc).wait(0xc0001be418, 0x72, 0xc00006a100, 0x0, 0x0)
        /usr/local/go/src/internal/poll/fd_poll_runtime.go:85 +0x9a
internal/poll.(*pollDesc).waitRead(0xc0001be418, 0xffffffffffffff00, 0x0, 0x0)
        /usr/local/go/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc0001be400, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/internal/poll/fd_unix.go:384 +0x1a0
net.(*netFD).accept(0xc0001be400, 0x40d71f, 0xc0000a8140, 0xa0)
        /usr/local/go/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc0001ae2a0, 0xc0004bbd20, 0xe2fa0034, 0x40cb3d006f28230d)
        /usr/local/go/src/net/tcpsock_posix.go:139 +0x2e
net.(*TCPListener).AcceptTCP(0xc0001ae2a0, 0xc0004bbd48, 0x4b51b6, 0x5d01c65c)
        /usr/local/go/src/net/tcpsock.go:247 +0x47
net/http.tcpKeepAliveListener.Accept(0xc0001ae2a0, 0xc0004bbd98, 0x18, 0xc000000300, 0x6e9185)
        /usr/local/go/src/net/http/server.go:3232 +0x2f
net/http.(*Server).Serve(0xc000208b60, 0xc94240, 0xc0001ae2a0, 0x0, 0x0)
        /usr/local/go/src/net/http/server.go:2826 +0x22f
net/http.(*Server).ListenAndServe(0xc000208b60, 0xbdab48, 0xa)
        /usr/local/go/src/net/http/server.go:2764 +0xb6
JSDataManager/manager/serverManager.StartToListen(0x0, 0xbb244c)
        /home/seeta/wjx/jiesi_data/manager/serverManager/ServerMananger.go:63 +0x4e
main.main()
        /home/seeta/wjx/jiesi_data/main.go:42 +0x257
...
=== END goroutine stack dump ===

参考资料:

https://stackoverflow.com/questions/19094099/how-to-dump-goroutine-stacktraces

你可能感兴趣的:(Golang)