在go web中,定位内存/cpu问题(内存泄漏,内存优化)可以这么做。
import _ "net/http/pprof"
func main() {
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
...
此时,可以在web浏览器中输入http://localhost:6060/debug/pprof/
,并点击进入 heap,查看信息。
重要的数据在下面:
# runtime.MemStats
# Alloc = 1950440
# TotalAlloc = 6346404496
# Sys = 27572472
Alloc 指当前分配的内存,Sys指向系统申请的内存。正常情况下,Alloc的数值应该呈波动状(因为GC)。 这样,就能比较容易的发现内存泄漏的情况。
但是,上面的信息还不足以优化代码,进入命令行,输入命令如下:
go tool pprof -alloc_space http://localhost:6060/debug/pprof/heap
此时进入交互界面,输入 top -cum
。
举例:
top -cum
...
28MB 0.44% 29.40% 1532.19MB 24.24% gcount/handlers.getArticleCount
这里先讲下几个标准:
主要关注cum和flat就行了。 因为cum是链式的资源总合,我们很容易找到消耗链,然后使用list查看具体代码。具体上,我们关注flat的值就行了,找出大的优化它。
上面的例子中,getArticleCount 累计消耗1532M 内存。此时,用list查询这个函数,在交互界面输入
list getArticleCount
ROUTINE ======================== gcount/handlers.getArticleCount in handlers/ getclick.go
28MB 1.50GB (flat, cum) 24.24% of Total
. . 15:)
. . 16:
. . 17://GetArticleCount传入id_list,返回相关文章点击量
. . 18:func getArticleCount(r *http.Request) (interface{}, int) {
. . 19: logger.Debug("getArticleCount run")
. 186.54MB 20: id_list := httpHelper.GetReqKey(r, "id_list")
...
最上面一行是总量,然后是每行代码对应的内存消耗。 多调用几次list深挖,就能找出内存消耗的元凶啦。
输入命令
go tool pprof ./msg_topic_manager http://193.112.83.241:6060/debug/pprof/profile
等待一会,进入交互界面。
输入top10
,查看cpu前十名:
发现第一名是syscall.Syscall,看不出来,我们继续。
输入top -cum
有点意思了,我们一路list,找到了关键地方:
从上面的图分析,可以发现cpu的消耗,主要在: