1. 概述
在 go 語言中,主要關注的應用運行情況主要包括以下幾種:
- CPU Profiling:CPU 分析劲弦,按照一定的頻率采集所監(jiān)聽的應用程序 CPU(含寄存器)的使用情況打掘,可確定應用程序在主動消耗 CPU 周期時花費時間的位置
- Memory Profiling:內存分析,在應用程序進行堆分配時記錄堆棧跟蹤,用于監(jiān)視當前和歷史內存使用情況辰斋,以及檢查內存泄漏
- Goroutine Profiling:報告 goroutines 的使用情況代芜,有哪些 goroutine埠褪,它們的調用關系是怎樣的
- Block Profiling:阻塞分析,記錄 goroutine 阻塞等待同步(包括定時器通道)的位置,可以用來分析和查找死鎖等性能瓶頸
- Mutex Profiling:互斥鎖分析蜒犯,報告互斥鎖的競爭情況
1.1 pprof
PProf是一個CPU分析器( cpu profiler)组橄, 它是gperftools工具的一個組件, 由Google工程師為分析多線程的程序所開發(fā)罚随,是用于可視化和分析性能分析數(shù)據(jù)的工具
pprof 以 profile.proto 讀取分析樣本的集合玉工,并生成報告以可視化并幫助分析數(shù)據(jù)(支持文本和圖形報告)
profile.proto 是一個 Protocol Buffer v3 的描述文件,它描述了一組 callstack 和 symbolization 信息淘菩, 作用是表示統(tǒng)計分析的一組采樣的調用棧遵班,是很常見的 stacktrace 配置文件格式
1.2 支持什么使用模式
Report generation:報告生成
Interactive terminal use:交互式終端使用
Web interface:Web 界面
2 安裝依賴工具:
1) 安裝 PProf
$ go get -u github.com/google/pprof
2) 安裝 FlameGraph
cd $WORK_PATH
git clone https://github.com/brendangregg/FlameGraph.git
export PATH=$PATH:$WORK_PATH/FlameGraph
3)安裝 graphviz
pprof生成的prof文件時二進制的屠升,需要把這個二進制的文件轉換為我們人類可讀的,graphviz可以幫助我們把二進制的prof文件轉換為圖像
brew install graphviz
3 采集狭郑、分析數(shù)據(jù)
做 Profiling 第一步就是怎么獲取應用程序的運行情況數(shù)據(jù)腹暖。go 語言提供了兩個庫:
runtime/pprof:采集程序(非 Server)的運行數(shù)據(jù)進行分析
net/http/pprof:對runtime/pprof包進行簡單封裝,并在http端口上暴露出來翰萨,采集 HTTP Server 的運行時數(shù)據(jù)進行分析
核心工具是:go tool pprof 命令:獲取和分析 Profiling 數(shù)據(jù)
更詳細的 pprof 使用方法可以參考 pprof --help 或者 pprof 文檔脏答。
對于不同類型的應該也有不同的采集和分析方式
3.1 工具型應用
3.1.1 腳本類
如果你的應用是一次性的,運行一段時間就結束亩鬼。那么最好的辦法殖告,就是在應用退出的時候把 profiling 的報告保存到文件中,進行分析雳锋。對于這種情況黄绩,可以使用 runtime/pprof
庫。
pprof
封裝了很好的接口供我們使用玷过,比如要想進行 CPU Profiling爽丹,可以調用 pprof.StartCPUProfile()
方法,它會對當前應用程序進行 CPU profiling辛蚊,并寫入到提供的參數(shù)中(w io.Writer
)粤蝎,要停止調用 StopCPUProfile()
即可。
示例:
import (
"os"
"runtime/pprof"
)
func main() {
f, _ := os.Create("cpu.prof")
defer f.Close()
do somethings...
pprof.StopCPUProfile()
}
應用執(zhí)行結束后嚼隘,就會生成一個文件(cpu.prof)诽里,保存了我們的 CPU profiling 數(shù)據(jù)。
想要獲得內存的數(shù)據(jù)飞蛹,直接使用 WriteHeapProfile
就行谤狡,不用 start
和 stop
這兩個步驟了:
f, err := os.Create(*memprofile)
pprof.WriteHeapProfile(f)f.Close()
3.1.2 通過測試用例進行性能測試
編寫測試用例
(1)新建 data/d_test.go,文件內容:
package data
import "testing"
const url = "https://github.com/EDDYCJY"
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)
}
}
(2)執(zhí)行測試用例卧檐,生成prof文件
$go test -bench=. -cpuprofile=cpu.prof
pkg: github.com/EDDYCJY/go-pprof-example/data
BenchmarkAdd-410000000187ns/op
PASS
ok github.com/EDDYCJY/go-pprof-example/data2.300s
-memprofile 也可以了解一下
啟動 PProf 可視化界面
$go tool pprof -http=:8080 cpu.prof
3.2 服務型應用(web服務)
3.2.1 引入
如果你的應用是一直運行的墓懂,比如 web 應用,那么可以使用 net/http/pprof
庫霉囚,它能夠在提供 HTTP 服務進行分析捕仔。
import中只需要添加一行:
import _ "net/http/pprof"
main函數(shù)中啟動監(jiān)聽:
go func() {
if err := http.ListenAndServe(fmt.Sprintf("%s:%s", "0.0.0.0", "6060"), nil); nil != err {
panic(err)
}
}()
3.2.2 分析數(shù)據(jù)
3.2.2.1 通過 Web 界面
查看當前總覽:訪問 http://127.0.0.1:6060/debug/pprof/
/debug/pprof/
profiles:
0 block
5 goroutine
3 heap
0 mutex
9 threadcreate
full goroutine stack dump
這個頁面中有許多子頁面,咱們繼續(xù)深究下去盈罐,看看可以得到什么榜跌?
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帆调,查看創(chuàng)建新OS線程的堆棧跟蹤
pprof監(jiān)控的內容項目入下表所示。
3.2.2.1 通過交互式終端使用
能通過對應的庫獲取想要的 Profiling 數(shù)據(jù)之后(不管是文件還是 http)豆同,下一步就是要對這些數(shù)據(jù)進行保存和分析番刊,我們可以使用 go tool pprof
命令行工具。
(1)go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60
$ go tool pprof http://localhost:6060/debug/pprof/profile\?seconds\=60
Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=60
Saved profilein/Users/eddycjy/pprof/pprof.samples.cpu.007.pb.gz
Type: cpu
Duration: 1mins, Total samples = 26.55s (44.15%)
Entering interactive mode (type"help"forcommands,"o"foroptions)
(pprof)
執(zhí)行該命令后影锈,需等待 60 秒(可調整 seconds 的值)芹务,pprof 會進行 CPU Profiling。結束后將默認進入 pprof 的交互式命令模式精居,可以對分析的結果進行查看或導出锄禽。具體可執(zhí)行 pprof help 查看命令說明
(pprof) top10
Showing nodes accountingfor25.92s, 97.63% of 26.55s total
Dropped 85 nodes (cum <= 0.13s)
Showing top 10 nodes out of 21
flat flat% sum% cum cum%
23.28s 87.68% 87.68% 23.29s 87.72% syscall.Syscall
0.77s 2.90% 90.58% 0.77s 2.90% runtime.memmove
0.58s 2.18% 92.77% 0.58s 2.18% runtime.freedefer
0.53s 2.00% 94.76% 1.42s 5.35% runtime.scanobject
0.36s 1.36% 96.12% 0.39s 1.47% runtime.heapBitsForObject
0.35s 1.32% 97.44% 0.45s 1.69% runtime.greyobject
0.02s 0.075% 97.51% 24.96s 94.01% main.main.func1
0.01s 0.038% 97.55% 23.91s 90.06% os.(*File).Write
0.01s 0.038% 97.59% 0.19s 0.72% runtime.mallocgc
0.01s 0.038% 97.63% 23.30s 87.76% syscall.Write
flat:給定函數(shù)上運行耗時
flat%:同上的 CPU 運行耗時總比例
sum%:給定函數(shù)累積使用 CPU 總比例
cum:當前函數(shù)加上它之上的調用運行總耗時
cum%:同上的 CPU 運行耗時總比例
最后一列為函數(shù)名稱潜必,在大多數(shù)的情況下靴姿,我們可以通過這五列得出一個應用程序的運行情況,加以優(yōu)化
pprof 不僅能打印出最耗時的地方(top)磁滚,還能列出函數(shù)代碼以及對應的取樣數(shù)據(jù)(list)佛吓、匯編代碼以及對應的取樣數(shù)據(jù)(disasm),而且能以各種樣式進行輸出垂攘,比如 svg维雇、gv、callgrind晒他、png吱型、gif等等
(2)go tool pprof http://localhost:6060/debug/pprof/heap
$ go tool pprof http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profilein/Users/eddycjy/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.008.pb.gz
Type: inuse_space
Entering interactive mode (type"help"forcommands,"o"foroptions)
(pprof) top
Showing nodes accountingfor837.48MB, 100% of 837.48MB total
flat flat% sum% cum cum%
837.48MB 100% 100% 837.48MB 100% main.main.func1
-inuse_space:分析應用程序的常駐內存占用情況
-alloc_objects:分析應用程序的內存臨時分配情況
(3) go tool pprof http://localhost:6060/debug/pprof/block
(4) go tool pprof http://localhost:6060/debug/pprof/mutex
3.2.2.3 直接可視化查看(火焰圖)
只需添加一個參數(shù)-http并指定端口,即可直接在web頁面查看
go tool pprof -http=:8099 http://localhost:6060/debug/pprof/heap
或者通過pprof查看陨仅,效果是一樣的
$ pprof -http=:8099 http://localhost:6060/debug/pprof/heap
- 火焰圖
它的最大優(yōu)點是動態(tài)的津滞。調用順序由上到下(A -> B -> C -> D),每一塊代表一個函數(shù)灼伤,越大代表占用 CPU 的時間更長触徐。同時它也支持點擊塊深入進行分析!
- Top
- Graph
框越大狐赡,線越粗代表它占用的時間越大哦
- Peek
-
Source
通過 PProf 的可視化界面撞鹉,我們能夠更方便、更直觀的看到 Go 應用程序的調用鏈颖侄、使用情況等鸟雏,并且在 View 菜單欄中,還支持如上多種方式的切換
你想想览祖,在煩惱不知道什么問題的時候孝鹊,能用這些輔助工具來檢測問題,是不是瞬間效率翻倍了呢 ?
總結
在本章節(jié)穴墅,粗略地介紹了 Go 的性能利器 PProf惶室。在特定的場景中温自,PProf 給定位、剖析問題帶了極大的幫助
參考鏈接:
https://blog.csdn.net/cscrazybing/article/details/78686941
http://www.brendangregg.com/flamegraphs.html