Golang 大杀器之性能剖析 PProf

参考文章:

接触了那么久的go,一直也在用go写项目代码,有时遇到一些性能、内存问题,一时不好下手,幸好go自带性能大杀器,帮助我们及时知悉项目代码运行情况与cpu耗时、内存占用等一系列问题。

本次分享主要基于 Golang 大杀器之性能剖析 PProf 文档进行学习,感谢文章作者的分享,大家可以根据自己情况学习一波。

1.PProf概述

运用场景

想要进行性能优化,首先瞩目在 Go 自身提供的工具链来作为分析依据,本文将带你学习、使用 Go 后花园,涉及如下:

  • runtime/pprof:采集程序(非 Server)的运行数据进行分析
  • net/http/pprof:采集 HTTP Server 的运行时数据进行分析

PPro是什么

pprof 是用于可视化和分析性能分析数据的工具

pprof 以 profile.proto 读取分析样本的集合,并生成报告以可视化并帮助分析数据(支持文本和图形报告)

profile.proto 是一个 Protocol Buffer v3 的描述文件,它描述了一组 callstack 和 symbolization 信息, 作用是表示统计分析的一组采样的调用栈,是很常见的 stacktrace 配置文件格式

支持什么使用模式

  • Report generation:报告生成
  • Interactive terminal use:交互式终端使用
  • Web interface:Web 界面

用途

  • CPU Profiling:CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置
  • Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏
  • Block Profiling:阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置
  • Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况

2.demo演示

通过一个简单且有问题的例子,进行本次的程序分析。

相关代码

项目目录:

demo.go

package main
import (
"log"
"math/rand"
"net/http"
_ "net/http/pprof"
"time"
"go-pprof-abc/data"
)
func main() {
go func() {
rand.Seed(time.Now().UnixNano())
for {
var d int64 = rand.Int63n(3000)
time.Sleep(time.Duration(d) * time.Millisecond)
log.Println(data.Add("https://github.com/hahaha"))
}
}()
http.ListenAndServe("0.0.0.0:8080", nil)
}

d.go

package data
var datas []string
func Add(str string) string {
data := []byte(str)
sData := string(data)
datas = append(datas, sData)
return sData
}

分析

首先运行代码demo.go,我们在浏览器中访问,默认会在/debug/pprofurl中访问。

IDE看运行:

1.通过访问 http://localhost:8080/debug/pprof/

效果如图所示:

相关子页面:

cpu(CPU Profiling): $HOST/debug/pprof/profile,默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件
block(Block Profiling):$HOST/debug/pprof/block,查看导致阻塞同步的堆栈跟踪
goroutine:$HOST/debug/pprof/goroutine,查看当前所有运行的 goroutines 堆栈跟踪
heap(Memory Profiling): $HOST/debug/pprof/heap,查看活动对象的内存分配情况
mutex(Mutex Profiling):$HOST/debug/pprof/mutex,查看导致互斥锁的竞争持有者的堆栈跟踪
threadcreate:$HOST/debug/pprof/threadcreate,查看创建新OS线程的堆栈跟踪

通常我们比较关心的就是 cpu/block/heap/mutex 相关信息了。

2.通过命令行

  1. go tool pprof http://localhost:8080/debug/pprof/profile?seconds=20
    查看性能耗时
$ go tool pprof http://localhost:8080/debug/pprof/profile?seconds=20
Fetching profile over HTTP from http://localhost:8080/debug/pprof/profile?seconds=20
Saved profile in C:\Users\wendong\pprof\pprof.samples.cpu.002.pb.gz
Type: cpu
Time: Mar 22, 2023 at 11:19am (CST)
Duration: 20.01s, Total samples = 40ms ( 0.2%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top 10
Showing nodes accounting for 40ms, 100% of 40ms total
Showing top 10 nodes out of 26
flat flat% sum% cum cum%
10ms 25.00% 25.00% 10ms 25.00% os.(*File).checkValid (inline)
10ms 25.00% 50.00% 10ms 25.00% runtime.(*mheap).allocSpan
10ms 25.00% 75.00% 10ms 25.00% runtime.(*profBuf).read
10ms 25.00% 100% 10ms 25.00% runtime.startm
0 0% 100% 10ms 25.00% log.(*Logger).Output
0 0% 100% 10ms 25.00% log.Println
0 0% 100% 10ms 25.00% main.main.func1
0 0% 100% 10ms 25.00% os.(*File).Write
0 0% 100% 10ms 25.00% runtime.(*mcache).nextFree
0 0% 100% 10ms 25.00% runtime.(*mcache).refill

执行该命令后,需等待 60 秒(可调整 seconds 的值),pprof 会进行 CPU Profiling。结束后将默认进入 pprof 的交互式命令模式,可以对分析的结果进行查看或导出。具体可执行 pprof help 查看命令说明

相关显示:

flat:给定函数上运行耗时
flat%:同上的 CPU 运行耗时总比例
sum%:给定函数累积使用 CPU 总比例
cum:当前函数加上它之上的调用运行总耗时
cum%:同上的 CPU 运行耗时总比例
最后一列为函数名称,在大多数的情况下,我们可以通过这五列得出一个应用程序的运行情况,加以优化

2.go tool pprof http://localhost:8080/debug/pprof/heap
查看内存分配

$ go tool pprof http://localhost:8080/debug/pprof/heap
Fetching profile over HTTP from http://localhost:8080/debug/pprof/heap
Saved profile in C:\Users\wendong\pprof\pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz
Type: inuse_space
Time: Mar 22, 2023 at 11:23am (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 4135.63kB, 100% of 4135.63kB total
Showing top 10 nodes out of 35
flat flat% sum% cum cum%
1184.27kB 28.64% 28.64% 1184.27kB 28.64% runtime/pprof.StartCPUProfile
902.59kB 21.82% 50.46% 902.59kB 21.82% compress/flate.NewWriter
512.50kB 12.39% 62.85% 512.50kB 12.39% runtime.allocm
512.20kB 12.39% 75.24% 512.20kB 12.39% runtime.malg
512.05kB 12.38% 87.62% 512.05kB 12.38% regexp/syntax.(*parser).newRegexp (inline)
512.02kB 12.38% 100% 512.02kB 12.38% go-pprof-abc/data.Add (inline)
0 0% 100% 902.59kB 21.82% compress/gzip.(*Writer).Write
0 0% 100% 512.05kB 12.38% internal/profile.init
0 0% 100% 512.02kB 12.38% main.main.func1
0 0% 100% 1184.27kB 28.64% net/http.(*ServeMux).ServeHTTP
(pprof)
# -inuse_space:分析应用程序的常驻内存占用情况
# -alloc_objects:分析应用程序的内存临时分配情况

查看更多如 阻塞、互斥锁状态见下面命令:

go tool pprof http://localhost:8080/debug/pprof/block
go tool pprof http://localhost:8080/debug/pprof/mutex

4.通过pprof可视化界面

准备工作
在进行此操作前,请确认你已经安装 graphviz, 相关安装请移至参考文档。

另外建议先下载google的 pprof工具,其提供的火焰图比go 1.19自带的火焰图多更多的信息。

go install github.com/google/pprof@latest

编写测试用例
d_test.go

package data
import "testing"
const url = "http://github.com/hahaha"
func TestAdd(t *testing.T) {
s := Add(url)
if s == "" {
t.Errorf("Test.Add error!")
}
}
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(url)
}
}

执行测试用例

$ cd data
$ go test -bench=. -cpuprofile=cpu.prof -memprofile=mem.prof
goos: windows
goarch: amd64
pkg: go-pprof-abc/data
cpu: AMD Ryzen 7 4700U with Radeon Graphics
BenchmarkAdd-8 16872606 75.34 ns/op
PASS
ok go-pprof-abc/data 1.785s
# 测试生成cpu/mem的文件信息

启动pprof可视化界面

方法一:
$ go tool pprof -http=:8080 cpu.prof
方法二:
$ go tool pprof cpu.prof
$ (pprof) web

查看可视化界面

  • TOP

  • Graph

  • Flame Graph

看看 mem.prof

  • Top

  • Graph

  • Flame Graph


通过pprof工具查看

$ pprof -http=:8080 cpu.prof
Serving web UI on http://localhost:8080

pprof new flame graph

关于火焰图

火焰图最大优点是动态的。调用顺序由上到下(A -> B -> C -> D),每一块代表一个函数,越大代表占用 CPU 的时间更长。同时它也支持点击块深入进行分析!

posted on   进击的davis  阅读(720)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示