go是一门比较重视性能的语言,经常需要对程序进行性能分析和优化
首选的性能分析和优化工具为pprof
,常用的有两种
1、runtime/pprof
是一种导入性能分析日志到文件的形式
2、net/http/pprof
是一种WEB形式
配置介绍
- 本文介绍一下第2种,web形式的pprof调优
- 配置方式如下,在main函数中起一个goroutine,第一个参数为ip和port
import(
_ "net/http/pprof"
)
func main() {
go func() {
http.ListenAndServe("127.0.0.1:6060", nil)
}()
...
}
- 浏览器输入刚当的
ip:port/debug/pprof/
进入主页,本案例地址即为http://127.0.0.1:6060/debug/pprof/
- 可以直接点击allocs、goroutine、heap、mutex等查看对应的具体信息
案例介绍
- 下面以我本次调优的一个定时调度程序为例介绍下对
goroutine
的分析
我在程序运行中,使用runtime.NumGoroutine()
不断打印出groutine的数量,发现goroutine的数量随着程序的运行越来越多,如下所示
goroutine number: 12 ---- 0
goroutine number: 12 ---- 0
goroutine number: 15 ---- 3
goroutine number: 15 ---- 3
goroutine number: 18 ---- 6
goroutine number: 18 ---- 6
goroutine number: 21 ---- 5
goroutine number: 20 ---- 5
......
goroutine number: 162 ---- 8
goroutine number: 163 ---- 5
goroutine number: 162 ---- 5
goroutine number: 161 ---- 5
goroutine number: 161 ---- 5
goroutine number: 162 ---- 6
goroutine number: 162 ---- 6
- 一开始我以为是我自己起的goroutine执行完程序后没有关闭,我就对我写得go func进行了检查,并没有发现问题
- 最后通过前面介绍的
pprof
进行配置,查看goroutine的情况
- 根据内容可以发现,一共230个goroutine,竟然有一段代码起了210个goroutine,根据信息可以发现,问题出现在cron.go文件中的DelayIfStillRunning方法,这个方法是当一个任务在执行时发现当前有任务正在执行,因此会起一个goroutine监控等待任务执行结束再运行本次任务
- 程序在调试阶段,配置的定时周期比较随意,没有结合程序的具体运行时间,导致出现一直Delay延迟执行,那么这样就会产生大量goroutine出现
- 通过对问题分析之后,结合任务运行时间合理配置定时周期后重新测试,发现goroutine数量正常,一直在20左右波动,问题解决