0
点赞
收藏
分享

微信扫一扫

go内存分析工具介绍--pprof

善解人意的娇娇 2022-04-16 阅读 51
golang

本人小白,刚开始接触go就遇到了一个内存问题,在进行内存分析的时候发现了一下比较好的工具,在此留下记录。

废话不多说,直接开整。

什么是pprof:pprof是Go的性能分析工具,在程序运行过程中,可以记录程序的运行信息,可以是CPU使用情况、内存使用情况、goroutine运行情况等,当需要性能调优或者定位Bug时候,这些记录的信息是相当重要。

基本使用方法

使用pprof有多种方式,Go已经现成封装好了1个:net/http/pprof,使用简单的几行命令,就可以开启pprof,记录运行信息,并且提供了Web服务,能够通过浏览器和命令行2种方式获取运行数据。

废话不多说先上例子:

package main

import (
    "fmt"
    "net/http"
    _ "net/http/pprof"
)

func main() {
    // 开启pprof,监听请求
    ip := "0.0.0.0:6060"
    if err := http.ListenAndServe(ip, nil); err != nil {
        fmt.Printf("start pprof failed on %s\n", ip)
        os.Exit(1)
    }
    // end pprof

    // do something 下面是你的工程代码
    ........
}

如图所示,将代码添加到main方法中。然后就是打镜像——喝茶——等镜像制作——等镜像制作——等镜像制作……发布

下面我门来说一下主要的操作命令命令:

(一)获取堆栈信息

$ go tool pprof -inuse_space http://ip:amdin_port/debug/pprof/heap

-inuse_space参数就是当前服务使用的内存情况,还有一个-alloc_space参数是指服务启动以来总共分配的内存情况,前者更直观一些。

root@sns-ads-service06:~/pprof# go tool pprof -inuse_space http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profile in /root/pprof/pprof.123.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz
File: thriftcapture
Build ID: 1da7c49a46e05f63089a7eecbe14129ad3948566
Type: inuse_space
Time: Apr 14, 2022 at 1:51am (UTC)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)

1,这个命令执行完成后会生成内存信息的图例,如上图中第三行所示可打开内存图进行查看

Saved profile in /root/pprof/pprof.123.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz

这其中包含了程序名123,profile类型alloc已分配的内存,inuse代表使用中的内存。

关于命令,我只用到了2个,top和list,其他命令大家可以自行探索,不再赘述。(可以通过help命令查看所有命令)

2,top命令:按指标大小列出前10个函数,比如内存是按内存占用多少,CPU是按执行时间多少。

root@sns-ads-service06:~/pprof# go tool pprof -inuse_space http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profile in /root/pprof/pprof.thriftcapture.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz
File: thriftcapture
Build ID: 1da7c49a46e05f63089a7eecbe14129ad3948566
Type: inuse_space
Time: Apr 14, 2022 at 1:51am (UTC)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 9034.64kB, 100% of 9034.64kB total
Showing top 10 nodes out of 23
      flat  flat%   sum%        cum   cum%
 5120.23kB 56.67% 56.67%  5120.23kB 56.67%  main.CopyMulty
 2368.33kB 26.21% 82.89%  2368.33kB 26.21%  github.com/buger/goreplay/raw_socket_listener.NewListener
 1034.03kB 11.45% 94.33%  1034.03kB 11.45%  runtime.procresize
  512.05kB  5.67%   100%   512.05kB  5.67%  os.newFile
         0     0%   100%   512.05kB  5.67%  github.com/buger/goreplay/raw_socket_listener.(*Listener).readPcap.func1
         0     0%   100%   512.05kB  5.67%  github.com/buger/goreplay/rlog.(*RLogger).GetMemoryUsageRate
         0     0%   100%   512.05kB  5.67%  github.com/buger/goreplay/rlog.(*logWriter).ReadFile
         0     0%   100%  2368.33kB 26.21%  main.(*RAWInput).listen
         0     0%   100%  2368.33kB 26.21%  main.InitPlugins
         0     0%   100%  2368.33kB 26.21%  main.NewRAWInput
(pprof) root@sns-ads-service06:~/pprof# 

top会列出5个统计数据:

  • flat: 本函数占用的内存量。
  • flat%: 本函数内存占使用中内存总量的百分比。
  • sum%: 前面每一行flat百分比的和,比如第2行虽然的100% 是 100% + 0%。
  • cum: 是累计量,加入main函数调用了函数f,函数f占用的内存量,也会记进来。
  • cum%: 是累计量占总量的百分比。

3,list命令:查看某个函数的代码,以及该函数每行代码的指标信息,如果函数名不明确,会进行模糊匹配,

图表待补充

可以看到在main.main中的第25行占用了814.62MB内存,左右2个数据分别是flat和cum,含义和top中解释的一样。

(二)根据前后两次生成的图标进行内存使用情况的对比

通过对比可查看前后两个时段的内存变化。

$ go tool pprof -base pprof.thriftcapture.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz pprof.thriftcapture.alloc_objects.alloc_space.inuse_objects.inuse_space.002.pb.gz

(三)查看内存分配

wget http://localhost:6060/debug/pprof/heap?debug=1

这个命令其实就是把当前内存分配的详情文件抓了下来,本地会生成一个叫heap?debug=1的文件,看一看服务内存分配的具体情况,也可通过runtime.MemStats获取

具体文件内存自行产看

指标含义大致如下

以下指标可参考看runtime.MemStats中响应参数的说明
    Alloc      uint64 // 已申请且仍在使用的字节数
    TotalAlloc uint64 // 已申请的总字节数(已释放的部分也算在内)
    Sys        uint64 // 从系统中获取的字节数(下面XxxSys之和)虚拟内存
    Lookups    uint64 // 指针查找的次数
    Mallocs    uint64 // 申请内存的次数
    Frees      uint64 // 释放内存的次数
    // 主分配堆统计
    HeapAlloc    uint64 // 已申请且仍在使用的字节数
    HeapSys      uint64 // 从系统中获取的字节数
    HeapIdle     uint64 // 闲置span中的字节数
    HeapInuse    uint64 // 非闲置span中的字节数
    HeapReleased uint64 // 释放到系统的字节数
    HeapObjects  uint64 // 已分配对象的总个数
    // L低层次、大小固定的结构体分配器统计,Inuse为正在使用的字节数,Sys为从系统获取的字节数
    StackInuse  uint64 // 引导程序的堆栈
    StackSys    uint64
    MSpanInuse  uint64 // mspan结构体
    MSpanSys    uint64
    MCacheInuse uint64 // mcache结构体
    MCacheSys   uint64
    BuckHashSys uint64 // profile桶散列表
    GCSys       uint64 // GC元数据
    OtherSys    uint64 // 其他系统申请
    // 垃圾收集器统计
    NextGC       uint64 // 会在HeapAlloc字段到达该值(字节数)时运行下次GC
    LastGC       uint64 // 上次运行的绝对时间(纳秒)
    PauseTotalNs uint64
    PauseNs      [256]uint64 // 近期GC暂停时间的循环缓冲,最近一次在[(NumGC+255)%256]
    NumGC        uint32
    EnableGC     bool
    DebugGC      bool

(四) 查询goroutine相关信息


$ wget http://ip:admin_port/debug/pprof/goroutine?debug=1
$ wget http://ip:admin_port/debug/pprof/goroutine?debug=2

debug=1就是获取服务当前goroutine的数目和大致信息,debug=2获取服务当前goroutine的详细信息,分别在本地生成了goroutine?debug=1和goroutine?debug=2文件,

稍后补充图片信息

持续更新中。。。

参考文献: 实战Go内存泄露 - SegmentFault 思否 

举报

相关推荐

0 条评论