Profiling 是指在程序执行过程中,收集能够反映程序执行状态的数据。

Go 语言自带的 pprof 库就可以分析程序的运行情况,并且提供可视化的功能。它包含两个相关的库:
1.runtime/pprof:对于只跑一次的程序,例如每天只跑一次的离线预处理程序,调用 pprof 包提供的函数,手动开启性能数据采集。

2.net/http/pprof:对于在线服务,对于一个 HTTP Server,访问 pprof 提供的 HTTP 接口,获得性能数据。当然,实际上这里底层也是调用的 runtime/pprof 提供的函数,封装成接口对外提供网络访问。

image.png

如何使用:

1)首先是采集数据 - 两种方式
工具型应用
HTTP Server

2)然后就是进行分析了
Report generation:报告生成
Interactive terminal use:交互式终端使用
Web interface:Web 界面

工具型应用
如果你的应用程序是运行一段时间就结束退出类型。
那么最好的办法是在应用退出的时候把 profiling 的报告保存到文件中,进行分析。对于这种情况,可以使用 runtime/pprof 库。
import "runtime/pprof"

CPU

// 程序运行时开启统计
pprof.StartCPUProfile(w io.Writer)
// 程序结束时关闭
pprof.StopCPUProfile()

示例:

file, _ := os.Create("./cpu.pprof") // 在当前路径下创建一个cpu.pprof文件
pprof.StartCPUProfile(file) // 往文件中记录CPU profile信息
defer func() {
    // 退出之前 停止采集
    pprof.StopCPUProfile()
    file.Close()
}()

服务型应用
如果你的应用程序是一直运行的,比如 web 应用,那么可以使用 net/http/pprof 库,它能够在提供 HTTP 服务进行分析。
直接引入就行了
import _ "net/http/pprof"

Gin框架中引入 pprof 方式

imports "github.com/gin-contrib/pprof"

r:= gin.Default()
pprof.Register(r) // 性能

下载go-wrk
这个是用来进行http接口压测的, 下载地址: http://store.pibigstar.com/go-wrk.exe
官网地址:https://github.com/wg/wrk

压测:

go-wrk -d 500 http://localhost:8080/hello

web查看
浏览器打开:http://localhost:8080/debug/pprof/

  • allocs: 内存分配情况
  • block: 导致阻塞同步的堆栈跟踪
  • cmdline: 当前程序激活的命令行
  • goroutine: 当前运行的goroutine
  • heap: 存活对象的内存分配情况
  • mutex: 互斥锁的竞争持有者的堆栈跟踪
  • profile: 默认进行 30s 的 CPU Profiling
  • threadcreate: 操作系统线程跟踪
  • trace: 当前程序执行情况
  • full goroutine stack dump: 所有goroutine栈输出

数据分析

1.交互式命令

go tool pprof http://localhost:8080/debug/pprof/heap
然后在交互式命令行输入web即可跳转到默认浏览器:

示例:

# 下载cpu profile,默认从当前开始收集30s的cpu使用情况,需要等待30s
go tool pprof http://localhost:8080/debug/pprof/profile   #30-second CPU profile
go tool pprof http://localhost:8080/debug/pprof/profile?seconds=120 #wait 120s

# 下载heap profile
go tool pprof http://localhost:8080/debug/pprof/heap    #heap profile

# 下载goroutine profile
go tool pprof http://localhost:8080/debug/pprof/goroutine #goroutine profile

# 下载block profile
go tool pprof http://localhost:8080/debug/pprof/block   #goroutine blocking profile

# 下载mutex profile
go tool pprof http://localhost:8080/debug/pprof/mutex

常用命令

  • top n n不写默认显示10个占用CPU时间最多的函数
  • top -cum 将数据累计查看各个函数CPU占用
  • tree 树形结构查看goroutine情况。
  • list 方法名 查看方法名里面具体调用耗时时长。
  • web 生成SVG函数调用图(需安装graphviz
  • pdf 命令可以生成可视化的pdf文件
  • traces 打印所有调用栈
  • exit 退出分析
  • help 命令可以提供所有pprof支持的命令说明

list 可以查看某个函数的代码,以及该函数每行代码的指标信息,如果函数名不明确,会进行模糊匹配,比如list main会列出main.main和runtime.main

traces 打印所有调用栈,以及调用栈的指标信息。使用方式为traces+函数名(模糊匹配)

使用 top 命令:
image.png

每一行表示一个函数的信息。
flat:函数在 CPU 上运行的时间

flat%:函数在CPU上运行时间的百分比

sum%:是从上到当前行所有函数累加使用 CPU 的比例,如第二行sum=48.52=28.79+19.73

cum:这个函数以及子函数运行所占用的时间,应该大于等于flat

cum%:这个函数以及子函数运行所占用的比例,应该大于等于flat%

最后一列:函数的名字

我们可以在交互界面输入top(也可以指定个数 比如 top3)来查看程序中占用 CPU 比较多的函数:

http://localhost:8082/debug/pprof/ :获取概况信息,即图一的信息

go tool pprof http://localhost:8082/debug/pprof/allocs : 分析内存分配

go tool pprof http://localhost:8082/debug/pprof/cmdline : 分析命令行调用的程序,web下调用报错

go tool pprof http://127.0.0.1:8810/debug/pprof/goroutine       :所有goroutine的信息

go tool pprof http://127.0.0.1:8810/debug/pprof/heap            :堆内存的信息

go tool pprof http://127.0.0.1:8810/debug/pprof/profile         :CPU的使用情况

go tool pprof http://127.0.0.1:8810/debug/pprof/threadcreate    :线程信息

go tool pprof http://127.0.0.1:8810/debug/pprof/trace           :分析追踪当前程序的执行状况

go tool pprof http://127.0.0.1:8810/debug/pprof/mutex           :锁的信息

go tool pprof http://127.0.0.1:8810/debug/pprof/block           :goroutine的阻塞信息

##查看某条调用路径上,当前阻塞在此goroutine的数量:
http://127.0.0.1:8810/debug/pprof/goroutine?debug=1

##查看所有goroutine的运行栈(调用路径),可以显示阻塞了多久和原因:
http://127.0.0.1:8810/debug/pprof/goroutine?debug=2

2、svg
如果觉得在命令行查看不够直观的话,也可以直接输入web命令,生成 svg 图像进行查看。

关于图形的说明:
每个框代表一个函数,理论上框的越大表示占用的CPU资源越多。
方框之间的线条代表函数之间的调用关系,线条上的数字表示函数调用的次数。
方框中的第一行数字表示当前函数占用CPU的百分比,第二行数字表示当前函数累计占用CPU的百分比。

3、火焰图
使用 pprof生成或者 go-torch

go-torch Ubuntun 下安装

git clone https://github.com/brendangregg/FlameGraph.git
cp FlameGraph/flamegraph.pl /usr/local/bin
sudo apt-get install perl
go get -v github.com/uber/go-torch

## 使用,默认停留30秒收据 此期间内可使用hey工具对http服务进行压测
go-torch  http://192.168.1.12:8080/debug/pprof/profile

##压测:
go-wrk -d 500 http://localhost:8080

## 生成torch.tvg图片后拉到浏览器里即可

在输入命令:
go-torch -u http://127.0.0.1:8080,想生成火焰图,但是老是抛出错误:
ERROR: No stack counts found,could not generate flame graph: exit status 2。
发现必须在访问程序时,火焰图才能生成。因此通过命令去仿造批量请求:

windows下需要安装:
ActivePerl-5.28.1.0000-MSWin32-x64-92425271(需要加入到系统环境变量中)
FlameGraph/flamegraph.pl 需要加入到系统环境变量中。

安装graphviz:
https://graphviz.gitlab.io/_pages/Download/windows/graphviz-2...
需要加入到系统环境变量中。

生成svg火焰图之后,直接浏览器打开,
在浏览器中即可查看到相关信息了 view 中可以选择查询各种内容:

go tool pprof 自带方式(推荐):

方式一:

go tool pprof -http=:8082 http://localhost:8080/debug/pprof/profile
go tool pprof -http=:8082 http://localhost:8080/debug/pprof/goroutine

# 简单解释
# -http 表示使用交互式web接口查看获取的性能信息,指定可用的端口即可
# debug/pprof/需要查看的指标 (allocs,block,goroutine,heap...)

http://localhost:8082/ui/flamegraph

go tool trace 使用

curl http://127.0.0.1:8082/debug/pprof/trace?seconds=30 > trace.out
go tool trace trace.out  或者
go tool trace -http=localhost:8086  trace.out

go tool pprof 它可以显示在每个函数中花费的CPU时间的百分比。
go tool trace 更适合于找出程序在一段时间内正在做什么.

image.png

View trace:查看跟踪
Goroutine analysis:Goroutine 分析
Network blocking profile:网络阻塞概况
Synchronization blocking profile:同步阻塞概况
Syscall blocking profile:系统调用阻塞概况
Scheduler latency profile:调度延迟概况
User defined tasks:用户自定义任务
User defined regions:用户自定义区域
Minimum mutator utilization:最低 Mutator 利用率

View trace
最复杂、最强大和交互式的可视化显示了整个程序执行的时间轴。这个视图显示了在每个虚拟处理器上运行着什么,以及什么是被阻塞等待运行的,注意它只能在chrome上显示。

Goroutine analysis
显示了在整个执行过程中,每种类型的goroutines是如何创建的。在选择一种类型之后就可以看到关于这种类型的goroutine的信息。例如,在试图从mutex获取锁、从网络读取、运行等等每个goroutine被阻塞的时间。

Network/Sync/Syscall blocking profile
这些图表显示了goroutines在这些资源上所花费的时间。它们非常接近pprof上的内存/cpu分析。这是分析锁竞争的最佳选择。

Scheduler latency profiler
为调度器级别的信息提供计时功能,显示调度在哪里最耗费时间。

参考:

https://burxtx.github.io/2018/05/11/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAGo%E8%AF%AD%E8%A8%80%E6%89%A7%E8%A1%8C%E8%B7%9F%E8%B8%AA/

https://zhuanlan.zhihu.com/p/410590497
https://blog.csdn.net/RA681t58CJxsgCkJ31/article/details/96056719

方式二:
离线生成 gz 文件进行解析.

go tool pprof http://127.0.0.1:8082/debug/pprof/profile?-seconds=30
时间到后会生成一个类似pprof.samples.cpu.003.pb.gz的文件

go tool pprof -http=:8081 pprof.samples.cpu.001.pb.gz
在浏览器中即可查看到相关信息了 view 中可以选择查询各种内容

image.png

可视化图形监控—— debugcharts
一个可以实时查看golang程序内存、CPU、GC、协程等变化情况的可视化工具.
http://localhost:8080/debug/charts

package main

import (
    "fmt"
    "net/http"
    _ "net/http/pprof" // 必须,引入 pprof 模块
    "runtime"

    _ "github.com/mkevac/debugcharts" // 可选,添加后可以查看几个实时图表数据
)

func main() {
    c := runtime.GOMAXPROCS(10)
    fmt.Println(c)

    arr := []int{1, 2, 3}
    var newArr []*int
    for i, _ := range arr {
        newArr = append(newArr, &arr[i])
    }
    for _, v := range newArr {
        fmt.Println(*v)
    }

    http.ListenAndServe("0.0.0.0:8080", nil)
}

image.png


go可视化监控工具

pprof
debugcharts
expvar–非嵌入式
prometheus

使用示例:

_ "github.com/mkevac/debugcharts"
"github.com/prometheus/client_golang/prometheus/promhttp"
"net/http"
_ "net/http/pprof"


//监控
go func() {
 //提供给负载均衡探活
 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 w.Write([]byte("ok"))

 })

 //prometheus
 http.Handle("/metrics", promhttp.Handler())

 //pprof, go tool pprof -http=:8080 http://$host:$port/debug/pprof/heap
 http.ListenAndServe(":8080", nil)
}()

这个监控包也不错!!!!
https://github.com/arl/statsviz?tab=readme-ov-file

参考文章:
https://segmentfault.com/a/1190000019222661

https://blog.csdn.net/weixin_37717557/article/details/108684433

https://segmentfault.com/a/1190000041261187?utm_source=sf-similar-article


goper
413 声望26 粉丝

go 后端开发