這個(gè) Go 程序分析工具太帥了
源碼地址:https://github.com/pyroscope-io/pyroscope/tree/main/examples/golang-push。
使用Pyroscope — 一個(gè)開源的持續(xù)分析平臺(tái)

使用Pyroscope分析Golang Rideshare應(yīng)用程序
在這個(gè)例子中,展示了一個(gè)基本的用例,即如何使用Pyroscope[2](一個(gè)開源的分析庫)來加速Golang應(yīng)用程序使用持續(xù)分析。
我們模擬了一家"拼車"公司,該公司在 main.go 中有三個(gè)路徑endpoint(這里endpoint翻譯參考 阮一峰[3] 寫的RESTful API 設(shè)計(jì)指南[4]中的翻譯):
/bike:調(diào)用OrderBike(searchRadius)函數(shù)來訂購一輛自行車/car:調(diào)用OrderCar(searchRadius)函數(shù)訂購一輛汽車/scooter:調(diào)用OrderScooter(searchRadius)函數(shù)來訂購一輛踏板車
我還模擬在3個(gè)不同的區(qū)域運(yùn)行3個(gè)不同的服務(wù)器(通過docker-compose.yml[5])
美國東部-1 美國西部-1 歐洲西部-1
Pyroscope 最有用的功能之一是能夠以對(duì)你有意義的方式標(biāo)記數(shù)據(jù)。在本例中,我們有兩個(gè)自然劃分,因此我們"標(biāo)記"我們的數(shù)據(jù)來表示它們:
區(qū)域 region:靜態(tài)地標(biāo)記運(yùn)行代碼的服務(wù)器的區(qū)域車輛 vehicle:動(dòng)態(tài)地標(biāo)記路徑(類似于標(biāo)記控制器軌道的方式)
對(duì)區(qū)域進(jìn)行靜態(tài)標(biāo)記
標(biāo)記靜態(tài)內(nèi)容(如region)可以在 main() 函數(shù)的初始化代碼中完成:
?pyroscope.Start(pyroscope.Config{
??ApplicationName:?"ride-sharing-app",
??ServerAddress:???serverAddress,
??Logger:??????????pyroscope.StandardLogger,
??Tags:????????????map[string]string{"region":?os.Getenv("REGION")},
?})
在函數(shù)內(nèi)進(jìn)行動(dòng)態(tài)標(biāo)記
像我們?yōu)檐囕vvehicle標(biāo)記的那樣,可以在我們的實(shí)用函數(shù)FindNearestVehicle()中使用pyroscope.TagWrapper() 來動(dòng)態(tài)地標(biāo)記一些東西。
func?FindNearestVehicle(search_radius?int64,?vehicle?string)?{
??
?pyroscope.TagWrapper(context.Background(),?pyroscope.Labels("vehicle",?vehicle),?func(ctx?context.Context)?{
?????
????????//?模擬找到一輛車?Mock?"doing?work"?to?find?a?vehicle?
????????var?i?int64?=?0
????????start_time?:=?time.Now().Unix()
????????for?(time.Now().Unix()?-?start_time)??????????????i++
????????}
?????})
}
這塊的功能是:
它添加了標(biāo)簽 pyroscope.Labels("vehicle", vehicle)它執(zhí)行 FindNearestVehicle()函數(shù)在塊結(jié)束之前,它(在幕后)從應(yīng)用程序中移除了 pyroscope.Labels("vehicle", vehicle),因?yàn)樵搲K已經(jīng)執(zhí)行完成。
使用火焰圖顯示性能瓶頸

在分析應(yīng)用程序的配置文件輸出時(shí),第一步是注意最大的節(jié)點(diǎn),即應(yīng)用程序消耗最多資源的地方。在本例中,它恰好是 OrderCar() 函數(shù)。
使用Pyroscope包的好處是,現(xiàn)在我們可以進(jìn)一步研究為什么OrderCar()函數(shù)會(huì)有問題。標(biāo)記region和vehicle使我們可以對(duì)兩個(gè)很好的假設(shè)進(jìn)行測(cè)試:
/car路徑的代碼有問題我們的某個(gè)地區(qū) region有問題
要對(duì)此進(jìn)行分析,我們可以從"Select Tag"下拉列表中選擇一個(gè)或多個(gè)標(biāo)簽:

使用標(biāo)簽縮小性能問題的范圍
知道 OrderCar() 函數(shù)存在問題后,我們會(huì)自動(dòng)選擇該標(biāo)簽。然后,在檢查多個(gè)region標(biāo)簽后,通過查看時(shí)間線可以清楚地看出 us-west-1 區(qū)域存在問題,它在高 CPU 時(shí)間和低 CPU 時(shí)間之間交替。
我們還可以看到,mutexLock() 函數(shù)消耗了近 70% 的 CPU 資源。

比較兩個(gè)時(shí)間段
使用Pyroscope的"比較視圖-comparison view",我們可以從時(shí)間軸中選擇兩個(gè)不同的時(shí)間范圍來比較生成的火焰圖。左側(cè)時(shí)間軸上的粉紅色部分生成左側(cè)火焰圖,右側(cè)的藍(lán)色部分表示右側(cè)火焰圖。
當(dāng)我們選擇低 CPU 使用率周期和高 CPU 使用率周期時(shí),我們可以看到 mutexLock() 函數(shù)中存在不同的行為 ,其中它在低 CPU 時(shí)間占用 33% 的 CPU,在高 CPU 時(shí)間占用 71% 的 CPU。

可視化兩個(gè)火焰圖之間約有 112% 的性能差異
雖然在這種情況下,差異是很顯而易見的,但有時(shí)兩個(gè)火焰圖之間的差異最好通過相互疊加才能更好地可視化。無需更改任何參數(shù),我們只需選擇**(Diff View)差異視圖選項(xiàng)卡**,即可查看顏色編碼的差異火焰圖中表示的差異。

更多用例
無論你是從事副業(yè)的開發(fā)人員,還是一個(gè)想知道"如何加快我的Go應(yīng)用程序"的DevOps工程師,Pyroscope都有許多用例,可以輕松了解如何分析您的應(yīng)用程序。下面是一些示例:
標(biāo)記 Kubernetes 屬性 標(biāo)記控制器 標(biāo)記區(qū)域 標(biāo)記隊(duì)列中的任務(wù) 標(biāo)記提交 標(biāo)記生產(chǎn)環(huán)境 標(biāo)記測(cè)試套件的不同部分
未來路線圖
如果你想嘗試此示例,并查看如何將其調(diào)整到您的Go應(yīng)用程序,請(qǐng)單擊github上此示例[6]的鏈接。持續(xù)分析已成為監(jiān)視和調(diào)試性能問題(可以說是可觀察性的第四個(gè)支柱)的日益流行的工具。
如果您對(duì)Pyroscope[7]如何改進(jìn)有想法,請(qǐng)隨時(shí)在GitHub頁面上提交你的問題!感謝您的閱讀。
參考資料
Continuous Profiling for Go Applications: https://betterprogramming.pub/continuous-profiling-go-applications-8cdbdfdfc5ab
[2]Pyroscope: https://github.com/pyroscope-io/pyroscope
[3]阮一峰: https://www.ruanyifeng.com/
[4]RESTful API 設(shè)計(jì)指南: https://www.ruanyifeng.com/blog/2014/05/restful_api.html
[5]docker-compose.yml: https://github.com/pyroscope-io/pyroscope/blob/main/examples/golang-push/rideshare/docker-compose.yml
[6]github上此示例: https://github.com/pyroscope-io/pyroscope/blob/main/examples/golang-push/README.md
[7]Pyroscope: https://pyroscope.io/
推薦閱讀
