前言
寫了幾噸代碼,實現了幾百個接口。功能測試也通過了,終于成功的部署上線了
結果,性能不佳,什么鬼?
想做性能分析?
PProf
想要進行性能優化,首先矚目在 Go 自身提供的工具鏈來作為分析依據,本文將帶你學習、使用 Go 后花園,涉及如下:
- runtime/pprof:采集程序(非 Server)的運行數據進行分析
- net/http/pprof:采集 HTTP Server 的運行時數據進行分析
是什么
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:互斥鎖分析,報告互斥鎖的競爭情況
一個簡單的例子
我們將編寫一個簡單且有點問題的例子,用于基本的程序初步分析
編寫 demo 文件
(1)demo.go,文件內容:
(2)data/d.go,文件內容:
運行這個文件,你的 HTTP 服務會多出 /debug/pprof 的 endpoint 可用于觀察應用程序的情況
分析
一、通過 Web 界面
這個頁面中有許多子頁面,咱們繼續深究下去,看看可以得到什么?
- 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線程的堆棧跟蹤
二、通過交互式終端使用
執行該命令后,需等待 60 秒(可調整 seconds 的值),pprof 會進行 CPU Profiling。結束后將默認進入 pprof 的交互式命令模式,可以對分析的結果進行查看或導出。具體可執行 pprof help 查看命令說明
(pprof) top10 Showing nodes accounting for 25.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:給定函數上運行耗時
- flat%:同上的 CPU 運行耗時總比例
- sum%:給定函數累積使用 CPU 總比例
- cum:當前函數加上它之上的調用運行總耗時
- cum%:同上的 CPU 運行耗時總比例
最后一列為函數名稱,在大多數的情況下,我們可以通過這五列得出一個應用程序的運行情況,加以優化
- -inuse_space:分析應用程序的常駐內存占用情況
- -alloc_objects:分析應用程序的內存臨時分配情況
三、PProf 可視化界面
這是令人期待的一小節。在這之前,我們需要簡單的編寫好測試用例來跑一下
編寫測試用例
(1)新建 data/d_test.go,文件內容:
(2)執行測試用例
-memprofile 也可以了解一下
啟動 PProf 可視化界面
方法一:
$ go tool pprof -http=:8080 cpu.prof
方法二:
$ go tool pprof cpu.prof $ (pprof) web
如果出現 Could not execute dot; may need to install graphviz.,就是提示你要安裝 graphviz 了 (請右拐谷歌)
查看 PProf 可視化界面
(1)Top
(2)Graph
框越大,線越粗代表它占用的時間越大哦
(3)Peek
(4)Source
通過 PProf 的可視化界面,我們能夠更方便、更直觀的看到 Go 應用程序的調用鏈、使用情況等,并且在 View 菜單欄中,還支持如上多種方式的切換
你想想,在煩惱不知道什么問題的時候,能用這些輔助工具來檢測問題,是不是瞬間效率翻倍了呢
四、PProf 火焰圖
另一種可視化數據的方法是火焰圖,需手動安裝原生 PProf 工具:
(3) 查看 PProf 可視化界面
打開 PProf 的可視化界面時,你會明顯發現比官方工具鏈的 PProf 精致一些,并且多了 Flame Graph(火焰圖)
它就是本次的目標之一,它的最大優點是動態的。調用順序由上到下(A -> B -> C -> D),每一塊代表一個函數,越大代表占用 CPU 的時間更長。同時它也支持點擊塊深入進行分析!
總結
在本章節,粗略地介紹了 Go 的性能利器 PProf。在特定的場景中,PProf 給定位、剖析問題帶了極大的幫助
希望本文對你有所幫助,另外建議能夠自己實際操作一遍,最好是可以深入琢磨一下,內含大量的用法、知識點
思考題
你很優秀的看到了最后,那么有兩道簡單的思考題,希望拓展你的思路
(1)flat 一定大于 cum 嗎,為什么?什么場景下 cum 會比 flat 大?
(2)本章節的 demo 代碼,有什么性能問題?怎么解決它?
本文作者:煎魚,原創授權發布