使用gops轻松监控golang程序和性能分析
什么是gops
gops是google开发的一个在你系统上列出和分析golang程序的工具。它也是一个golang的库,当你集成这个库以后,分析golang程序会变得很简单。
安装
go get -u github.com/google/gops
在你的程序中启动gops的agent
package main
import (
"log"
"time"
"github.com/google/gops/agent"
)
func main() {
if err := agent.Listen(agent.Options{
Addr: "listen tcp address", // 你想监听的地址,不填的话系统会自动分配一个端口给它用。
}); err != nil {
log.Fatal(err)
}
time.Sleep(time.Hour)
}
gops使用
当你的程序嵌入了gops的agent,那么你就可以对你的golang程序进行诊断了。
除了诊断golang程序,gops程序也可以列出当前系统的golang程序和其系统,即时那些golang程序没有嵌入gops的agent。
注意的是只有程序嵌入了gops的agent才可以进行程序的分析,包括程序的堆、内存信息、cpu性能分析等
列出所有golang程序
$ gops
983 980 uplink-soecks go1.9 /usr/local/bin/uplink-soecks
52697 52695 gops go1.10 /Users/jbd/bin/gops
4132 4130 foops * go1.9 /Users/jbd/bin/foops
51130 51128 gocode go1.9.2 /Users/jbd/bin/gocode
$ gops tree
...
├── 1
│ └── 13962 [gocode] {go1.9}
├── 557
│ └── 635 [com.docker.supervisor] {go1.9.2}
│ └── 638 [com.docker.driver.amd64-linux] {go1.9.2}
└── 13744
└── 67243 [gops] {go1.10}
$ gops <pid>
parent PID: 5985
threads: 27
memory usage: 0.199%
cpu usage: 0.139%
username: jbd
cmd+args: /Applications/Splice.app/Contents/Resources/Splice Helper.app/Contents/MacOS/Splice Helper -pid 5985
local/remote: 127.0.0.1:56765 <-> :0 (LISTEN)
local/remote: 127.0.0.1:56765 <-> 127.0.0.1:50955 (ESTABLISHED)
local/remote: 100.76.175.164:52353 <-> 54.241.191.232:443 (ESTABLISHED)
打印指定程序的堆栈信息
用于显示程序所有堆栈信息,包括每个 goroutine 的堆栈信息、运行状态等。
$ gops stack (<pid>|<addr>)
gops stack 85709
goroutine 20 [running]:
runtime/pprof.writeGoroutineStacks(0x1197600, 0xc0000f0000, 0x30, 0xc000076000)
/Users/boya/golang/go/src/runtime/pprof/pprof.go:679 +0x9d
runtime/pprof.writeGoroutine(0x1197600, 0xc0000f0000, 0x2, 0x4ed28d60, 0xeaf54e38f8079f88)
/Users/boya/golang/go/src/runtime/pprof/pprof.go:668 +0x44
runtime/pprof.(*Profile).WriteTo(0x1275c40, 0x1197600, 0xc0000f0000, 0x2, 0xc0000f0000, 0x0)
/Users/boya/golang/go/src/runtime/pprof/pprof.go:329 +0x3da
github.com/google/gops/agent.handle(0x4211008, 0xc0000f0000, 0xc0000e0000, 0x1, 0x1, 0x0, 0x0)
/Users/boya/gopath/pkg/mod/github.com/google/gops@v0.3.6/agent/agent.go:181 +0x1ab
github.com/google/gops/agent.listen()
/Users/boya/gopath/pkg/mod/github.com/google/gops@v0.3.6/agent/agent.go:129 +0x275
created by github.com/google/gops/agent.Listen
/Users/boya/gopath/pkg/mod/github.com/google/gops@v0.3.6/agent/agent.go:110 +0x364
goroutine 1 [sleep]:
runtime.goparkunlock(...)
/Users/boya/golang/go/src/runtime/proc.go:310
time.Sleep(0x34630b8a000)
/Users/boya/golang/go/src/runtime/time.go:105 +0x157
main.main()
/Users/boydzheng/program/go/learn/Learning_go/gops/main.go:14 +0xa3
goroutine 19 [syscall]:
os/signal.signal_recv(0x0)
/Users/boya/golang/go/src/runtime/sigqueue.go:144 +0x96
os/signal.loop()
/Users/boya/golang/go/src/os/signal/signal_unix.go:23 +0x22
created by os/signal.init.0
/Users/boya/golang/go/src/os/signal/signal_unix.go:29 +0x41
# ...
goroutine 20 [running]
这里的 20
表示goroutine的id,它是在每个go进程中是全局唯一的。running
表示正在运行状态。
打印指定程序的内存占有信息
查看程序当前的内存统计信息
$ gops memstats (<pid>|<addr>)
gops memstats 40515
alloc: 2.14MB (2247328 bytes)
total-alloc: 2.14MB (2247328 bytes)
sys: 68.31MB (71631096 bytes)
lookups: 0
mallocs: 417
frees: 6
heap-alloc: 2.14MB (2247328 bytes)
heap-sys: 63.66MB (66748416 bytes)
heap-idle: 61.05MB (64012288 bytes)
heap-in-use: 2.61MB (2736128 bytes)
heap-released: 60.98MB (63946752 bytes)
heap-objects: 411
stack-in-use: 352.00KB (360448 bytes)
stack-sys: 352.00KB (360448 bytes)
stack-mspan-inuse: 10.36KB (10608 bytes)
stack-mspan-sys: 16.00KB (16384 bytes)
stack-mcache-inuse: 13.56KB (13888 bytes)
stack-mcache-sys: 16.00KB (16384 bytes)
other-sys: 787.56KB (806457 bytes)
gc-sys: 2.14MB (2240512 bytes)
next-gc: when heap-alloc >= 4.27MB (4473924 bytes)
last-gc: -
gc-pause-total: 0s
gc-pause: 0
num-gc: 0
enable-gc: true
debug-gc: false
打印golang版本
$ gops version (<pid>|<addr>)
gops version 40515
go1.13.5
打印runtime的统计信息
包括goroutines个数、线程个数、GOMAXPROCS和cpu数。
$ gops stats (<pid>|<addr>)
gops stats 40515
goroutines: 3
OS threads: 8
GOMAXPROCS: 8
num CPU: 8
生成cpu性能文件
采集30s的CPU的性能分析数据并且保存在文件中,用go自带的性能分析工具进行分析,效果等价于go tool pprof
。
显示的信息中会告诉你文件保存的路径。
$ gops pprof-cpu (<pid>|<addr>)
gops pprof-cpu 40515
Profiling CPU now, will take 30 secs...
Profile dump saved to: /var/folders/r8/yjb25qtj0xng2vmkrtjfrwc913t5c8/T/profile919446242
Profiling dump saved to: /var/folders/r8/yjb25qtj0xng2vmkrtjfrwc913t5c8/T/profile919446242
Binary file saved to: /var/folders/r8/yjb25qtj0xng2vmkrtjfrwc913t5c8/T/binary227917017
File: binary227917017
Type: cpu
Time: Jan 14, 2020 at 10:02am (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) top
Showing nodes accounting for 0, 0% of 0 total
flat flat% sum% cum cum%
(pprof)
生成堆信息文件
采集当前heap的性能分析数据并且保存在文件中,用go自带的性能分析工具进行分析,效果等价于go tool pprof
。
显示的信息中会告诉你文件保存的路径。
$ gops pprof-heap (<pid>|<addr>)
gops pprof-heap 40515
Profile dump saved to: /var/folders/r8/yjb25qtj0xng2vmkrtjfrwc913t5c8/T/profile801546231
Profiling dump saved to: /var/folders/r8/yjb25qtj0xng2vmkrtjfrwc913t5c8/T/profile801546231
Binary file saved to: /var/folders/r8/yjb25qtj0xng2vmkrtjfrwc913t5c8/T/binary652763370
File: binary652763370
Type: inuse_space
Time: Jan 14, 2020 at 10:04am (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 902.59kB, 100% of 902.59kB total
flat flat% sum% cum cum%
902.59kB 100% 100% 902.59kB 100% compress/flate.NewWriter
0 0% 100% 902.59kB 100% compress/gzip.(*Writer).Write
0 0% 100% 902.59kB 100% runtime/pprof.(*profileBuilder).build
0 0% 100% 902.59kB 100% runtime/pprof.profileWriter
(pprof)
采用http方式
http的方式也很简单,来自官方的文档https://golang.org/pkg/net/http/pprof/
package main
import _ "net/http/pprof"
func main() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// do things
}
结合go tool pprof
工具来使用,具体可查看https://golang.org/pkg/net/http/pprof/。
总结
不管是采用哪种方式(gops或者http/pprof),都建议在程序中添加其中一种采集程序信息的方式,这对程序的优化和问题分析都很有帮助。
ref
https://github.com/google/gops
https://golang.org/pkg/net/http/pprof/