golang性能優(yōu)化之pprof及其火焰圖

1 pprof簡介

golang代碼的性能監(jiān)控使用pprof包來做躬它。pprof有兩個包:

  • runtime/pprof
    pprof的具體實(shí)現(xiàn),所有類型的代碼都可以使用妇菱。如果不是Web應(yīng)用程序晦墙,建議使用該包。
  • net/http/pprof
    runtime/pprof包進(jìn)行簡單封裝挨务,并在http端口上暴露出來。適合Web應(yīng)用程序使用挥唠。

2 pprof監(jiān)控內(nèi)容

pprof監(jiān)控的內(nèi)容項(xiàng)目入下表所示仅叫。

類型 描述 備注
allocs 內(nèi)存分配情況的采樣信息 可以用瀏覽器打開,但可讀性不高
blocks 阻塞操作情況的采樣信息 可以用瀏覽器打開已添,但可讀性不高
cmdline 顯示程序啟動命令及參數(shù) 可以用瀏覽器打開朝巫,但可讀性不高
goroutine 當(dāng)前所有協(xié)程的堆棧信息 可以用瀏覽器打開鸿摇,但可讀性不高
heap 堆上內(nèi)存使用情況的采樣信息 可以用瀏覽器打開,但可讀性不高
mutex 鎖爭用情況的采樣信息 可以用瀏覽器打開劈猿,但可讀性不高
profile CPU 占用情況的采樣信息 瀏覽器打開會下載文件
threadcreate 系統(tǒng)線程創(chuàng)建情況的采樣信息 可以用瀏覽器打開拙吉,但可讀性不高
trace 程序運(yùn)行跟蹤信息 瀏覽器打開會下載文件

3 使用pprof進(jìn)行監(jiān)控

一下兩種使用pprof進(jìn)行性能監(jiān)控的方式只能生成監(jiān)控信息文件,具體的分析需要使用go tool pprof [binary] file進(jìn)行查看和分析揪荣。

3.1 非Web應(yīng)用程序

非Web應(yīng)用程序使用包runtime/pprof庐镐,生成監(jiān)控文件。
下面示例進(jìn)行CPU監(jiān)控变逃,并將監(jiān)控?cái)?shù)據(jù)存放在當(dāng)前項(xiàng)目的pprof/profile_file/profile_file文件中。

import (
    "log"
    "os"
    "path/filepath"
    "runtime/pprof"
)
// 進(jìn)行CPU監(jiān)控
func CreateProfileFile() {
    dir, err := os.Getwd()
    if err != nil {
        log.Fatalln("get current directory failed.", err)
    }
    
    fileName := filepath.Join(dir, "pprof", "profile_file", "profile_file")
    f, _ := os.Create(fileName)
    // start to record CPU profile and write to file `f`
    _ = pprof.StartCPUProfile(f)
    // stop to record CPU profile
    defer pprof.StopCPUProfile()
    // TODO do something
}

3.2 Web應(yīng)用程序

Web應(yīng)用程序使用包net/http/pprof怠堪,可以搭建Web服務(wù)器查看監(jiān)控信息揽乱。通過http://locahost:6060/debug/pprof進(jìn)行查看相關(guān)的監(jiān)控信息文件。

import (
    "log"
    "net/http"
    _ "net/http/pprof"
    "os"
    "runtime"
)

func main() {
    log.SetFlags(log.Lshortfile | log.LstdFlags)
    log.SetOutput(os.Stdout)

    runtime.GOMAXPROCS(1)
    runtime.SetMutexProfileFraction(1)
    runtime.SetBlockProfileRate(1)

    go func() {
        if err := http.ListenAndServe(":6060", nil); err != nil {
            log.Fatal(err)
        }
        os.Exit(0)
    }()

注意
如果你使用自定義的 Mux粟矿,則需要手動注冊一些路由規(guī)則:

mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)

4 pprof監(jiān)控信息使用

golang原生自帶pprof工具的go tool pprof [binary] file命令進(jìn)入交互式終端來排查應(yīng)用程序的性能問題凰棉。其中,

  • binary
    正在執(zhí)行的二進(jìn)制可執(zhí)行程序陌粹,可選撒犀。
  • file
    pprof監(jiān)控生成的文件√椭龋可以是具體的文件如profile.pprof或舞,也可以是web站點(diǎn)的地址,如http://localhost:6060/debug/pprof/profile蒙幻。
    進(jìn)入終端之后映凳,排查性能問題的三個命令為:
  • top
    查看資源較高的調(diào)用。
  • list
    list 代碼片段查看問題代碼具體位置邮破。
  • web
    在Web Browser上圖形化顯示當(dāng)前的資源監(jiān)控內(nèi)容诈豌。需要事先安裝graphviz
    web命令的實(shí)際行為是產(chǎn)生一個 .svg文件抒和,并調(diào)用系統(tǒng)里設(shè)置的默認(rèn)打開 .svg 的程序打開它矫渔。如果系統(tǒng)里打開 .svg 的默認(rèn)程序并不是瀏覽器(比如代碼編輯器),需要設(shè)置一下默認(rèn)使用瀏覽器打開 .svg 文件摧莽。然后瀏覽器自動打開庙洼,可以看到:
    示例 block的監(jiān)控信息

如果需要其他命令,可以在pprof交互式終端里輸入help查看其他命令的使用方法。例如送膳,

  • svg
    生成svg圖员魏。
  • pdf
    生成pdf文件,顯示svg圖叠聋。
  • png
    生成png圖片撕阎,顯示svg圖。
  • ...
    當(dāng)然還有很多其他的命令和選項(xiàng)碌补,請自行學(xué)習(xí)驗(yàn)證虏束。

5 pprof監(jiān)控信息展示——火焰圖

火焰圖(Flame Graph)是 Bredan Gregg 創(chuàng)建的一種性能分析圖表,因?yàn)樗臉幼咏苹鹧娑妹谜隆olang性能監(jiān)控結(jié)果可以轉(zhuǎn)換成火焰圖來進(jìn)行直觀展示镇匀。火焰圖 svg 文件可以通過瀏覽器打開袜啃,它展示調(diào)用圖的最大優(yōu)點(diǎn)是火焰圖動態(tài)的——可以通過點(diǎn)擊每個方塊來分析它上層概況/下層詳細(xì)的內(nèi)容汗侵。
火焰圖的調(diào)用順序從下到上,每個方塊代表一個函數(shù)群发,它上面一層表示這個函數(shù)會調(diào)用哪些函數(shù)晰韵,方塊的大小代表了占用資源值的多少(例如,CPU使用時間的長短熟妓,內(nèi)存使用的大小等)雪猪。火焰圖的配色并沒有特殊的意義起愈,默認(rèn)的紅只恨、黃配色是為了更像火焰而已。
生成火焰圖抬虽,有兩種方式:go-torch(golang version < 1.10)和golang原生的pprof(golang version < 1.10+的pprof集成了火焰圖功能)官觅。

5.1 go-torch

go-torch是uber 開源的一個工具。go-torch可以直接讀取 golang 的監(jiān)控?cái)?shù)據(jù)文件斥赋,并生成一個火焰圖的 svg 文件缰猴。

go-torch工具使用非常簡單,最簡單的是使用go-torch的docker鏡像運(yùn)行疤剑,無需安裝go-torch滑绒。

  1. 首先進(jìn)行docker安裝(ubuntu)。其他操作系統(tǒng)的安裝參考codker安裝隘膘。
  2. 運(yùn)行g(shù)o-rorch鏡像 uber/go-torch 疑故。
    如果不知道相關(guān)命令,可以執(zhí)行$ sudo docker run uber/go-torch -h查看go-torch的使用幫助弯菊。
$ sudo docker run uber/go-torch -h
Usage:
  go-torch [options] [binary] <profile source>

pprof Options:
  -u, --url=         Base URL of your Go program (default:
                     http://localhost:8080)
      --suffix=      URL path of pprof profile (default: /debug/pprof/profile)
  -b, --binaryinput= File path of previously saved binary profile. (binary
                     profile is anything accepted by
                     https://golang.org/cmd/pprof)
      --binaryname=  File path of the binary that the binaryinput is for, used
                     for pprof inputs
  -t, --seconds=     Number of seconds to profile for (default: 30)
      --pprofArgs=   Extra arguments for pprof

Output Options:
  -f, --file=        Output file name (must be .svg) (default: torch.svg)
  -p, --print        Print the generated svg to stdout instead of writing to
                     file
  -r, --raw          Print the raw call graph output to stdout instead of
                     creating a flame graph; use with Brendan Gregg's flame
                     graph perl script (see
                     https://github.com/brendangregg/FlameGraph)
      --title=       Graph title to display in the output file (default: Flame
                     Graph)
      --width=       Generated graph width (default: 1200)
      --hash         Colors are keyed by function name hash
      --colors=      set color palette. choices are: hot (default), mem, io,
                     wakeup, chain, java, js, perl, red, green, blue, aqua,
                     yellow, purple, orange
      --cp           Use consistent palette (palette.map)
      --reverse      Generate stack-reversed flame graph
      --inverted     icicle graph

Help Options:
  -h, --help         Show this help message

最重要的命令有五個:

可選參數(shù)選項(xiàng) 描述 默認(rèn)值 備注
-u, --url= golang代碼的基礎(chǔ)URL——[scheme]://[host]:[port] http://localhost:8080
--suffix= pprof profile文件URL路徑 /debug/pprof/profile
-t, --seconds= 執(zhí)行profile的時間長度纵势,單位是秒 30
-f, --file= 輸出文件的名稱 torch.svg 文件擴(kuò)展名必須是 .svg
-p, --print 將生成的svg文件打印到標(biāo)準(zhǔn)輸出,而不是寫入文件

所有參數(shù)都是可選參數(shù)。如果沒有任何參數(shù)钦铁,默認(rèn)情況下软舌,會嘗試從http://localhost:8080/debug/pprof/profile 獲取監(jiān)控?cái)?shù)據(jù)。
例如牛曹,從服務(wù)器http://10.0.2.15:6060/debug/pprof/block獲取阻塞信息佛点,并將生成的svg文件打印到標(biāo)準(zhǔn)輸出中,然后信息重定向保存到本地torch.svg文件黎比。

$ sudo docker run uber/go-torch -u http://10.0.2.15:6060 --suffix=/debug/pprof/block -p > torch.svg
INFO[02:33:36] Run pprof command: go tool pprof -raw -seconds 30 http://10.0.2.15:6060/debug/pprof/block
INFO[02:33:36] Printing svg to stdout

第一次執(zhí)行由于需要安裝go-torch相關(guān)依賴和鏡像超营,等待時間較長。
執(zhí)行成功之后阅虫,本地會生成一個torch.svg文件演闭。右鍵通過瀏覽器打開,可以看到火焰圖颓帝,如下圖所示:


go-torch生成火焰圖示例

使用go-torch的docker鏡像可以在windows操作系統(tǒng)使用米碰。

注:當(dāng)然了,可以將go-torchFlameGraph工具分別安裝购城,然后執(zhí)行go-torch命令见间。具體參數(shù)和go-torch鏡像執(zhí)行-h顯示的參數(shù)相同。此處不再贅述工猜。

5.2 使用golang的pprof查看火焰圖

使用go tool pprof可以在Web界面上查看所有類型的資源監(jiān)控圖。
例如菱蔬,使用pprof查看Web服務(wù)器的阻塞監(jiān)控?cái)?shù)據(jù)篷帅,并將結(jié)果展示在6061端口。通過http://localhost:6062/ui/flamegraph即可查看生成的火焰圖拴泌。

$ go tool pprof -http=:6061 http://localhost:6060/debug/pprof/block
Fetching profile over HTTP from http://localhost:6060/debug/pprof/block
Saved profile in /home/jerry/pprof/pprof.___go_build_main_go.contentions.delay.005.pb.gz

從執(zhí)行命令的過程魏身,可以看到pprof工具從http://localhost:6060/debug/pprof/block獲取監(jiān)控?cái)?shù)據(jù),并保存到本地:/home/jerry/pprof/pprof.___go_build_main_go.contentions.delay.005.pb.gz蚪腐。然后對該文件進(jìn)行分析箭昵,并啟動一個Web服務(wù)器:http://localhost:6061。一般會自動彈出一個瀏覽器并顯示結(jié)果——默認(rèn)顯示的是graph回季。但是可以從第一行的菜單中切換View家制,選擇Flame Graph即可顯示火焰圖。

pprof啟動的性能分析圖形化默認(rèn)Web頁面

pprof啟動的性能分析圖形化火焰圖

參考

1 golang pprof 實(shí)戰(zhàn)
2 Go pprof和火焰圖
3 使用 pprof 和火焰圖調(diào)試 golang 應(yīng)用
4 go pprof詳細(xì)理解及使用
5 使用pprof及Go 程序的性能優(yōu)化

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泡一,一起剝皮案震驚了整個濱河市颤殴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鼻忠,老刑警劉巖涵但,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡矮瘟,警方通過查閱死者的電腦和手機(jī)瞳脓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澈侠,“玉大人劫侧,你說我怎么就攤上這事÷窠В” “怎么了板辽?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長棘催。 經(jīng)常有香客問我劲弦,道長,這世上最難降的妖魔是什么醇坝? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任邑跪,我火速辦了婚禮,結(jié)果婚禮上呼猪,老公的妹妹穿的比我還像新娘画畅。我一直安慰自己,他們只是感情好宋距,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布轴踱。 她就那樣靜靜地躺著,像睡著了一般谚赎。 火紅的嫁衣襯著肌膚如雪淫僻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天壶唤,我揣著相機(jī)與錄音雳灵,去河邊找鬼。 笑死闸盔,一個胖子當(dāng)著我的面吹牛悯辙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迎吵,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼躲撰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了击费?” 一聲冷哼從身側(cè)響起茴肥,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荡灾,沒想到半個月后瓤狐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞬铸,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年础锐,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗓节。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡皆警,死狀恐怖拦宣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情信姓,我是刑警寧澤鸵隧,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站意推,受9級特大地震影響豆瘫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜菊值,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一外驱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧腻窒,春花似錦昵宇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至柔逼,卻和暖如春杭煎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卒落。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜂桶,地道東北人儡毕。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像扑媚,于是被迫代替她去往敵國和親腰湾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容