Golang 大殺器之性能剖析 PProf

原文地址:Golang 大殺器之性能剖析 PProf

前言

寫了幾噸代碼,實(shí)現(xiàn)了幾百個(gè)接口。功能測(cè)試也通過(guò)了,終于成功的部署上線了

結(jié)果,性能不佳,什么鬼???

想做性能分析

PProf

想要進(jìn)行性能優(yōu)化,首先矚目在 Go 自身提供的工具鏈來(lái)作為分析依據(jù),本文將帶你學(xué)習(xí)、使用 Go 后花園,涉及如下:

  • runtime/pprof:采集程序(非 Server)的運(yùn)行數(shù)據(jù)進(jìn)行分析
  • net/http/pprof:采集 HTTP Server 的運(yùn)行時(shí)數(shù)據(jù)進(jìn)行分析

是什么

pprof 是用于可視化和分析性能分析數(shù)據(jù)的工具

pprof 以 profile.proto 讀取分析樣本的集合,并生成報(bào)告以可視化并幫助分析數(shù)據(jù)(支持文本和圖形報(bào)告)

profile.proto 是一個(gè) Protocol Buffer v3 的描述文件,它描述了一組 callstack 和 symbolization 信息, 作用是表示統(tǒng)計(jì)分析的一組采樣的調(diào)用棧,是很常見的 stacktrace 配置文件格式

支持什么使用模式

  • Report generation:報(bào)告生成
  • Interactive terminal use:交互式終端使用
  • Web interface:Web 界面

可以做什么

  • CPU Profiling:CPU 分析,按照一定的頻率采集所監(jiān)聽的應(yīng)用程序 CPU(含寄存器)的使用情況,可確定應(yīng)用程序在主動(dòng)消耗 CPU 周期時(shí)花費(fèi)時(shí)間的位置
  • Memory Profiling:內(nèi)存分析,在應(yīng)用程序進(jìn)行堆分配時(shí)記錄堆棧跟蹤,用于監(jiān)視當(dāng)前和歷史內(nèi)存使用情況,以及檢查內(nèi)存泄漏
  • Block Profiling:阻塞分析,記錄 goroutine 阻塞等待同步(包括定時(shí)器通道)的位置
  • Mutex Profiling:互斥鎖分析,報(bào)告互斥鎖的競(jìng)爭(zhēng)情況

一個(gè)簡(jiǎn)單的例子

我們將編寫一個(gè)簡(jiǎn)單且有點(diǎn)問題的例子,用于基本的程序初步分析

編寫 demo 文件

(1)demo.go,文件內(nèi)容:

package main

import (
    "log"
    "net/http"
    _ "net/http/pprof"
    "github.com/EDDYCJY/go-pprof-example/data"
)

func main() {
    go func() {
        for {
            log.Println(data.Add("https://github.com/EDDYCJY"))
        }
    }()

    http.ListenAndServe("0.0.0.0:6060", nil)
}

(2)data/d.go,文件內(nèi)容:

package data

var datas []string

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

    return sData
}

運(yùn)行這個(gè)文件,你的 HTTP 服務(wù)會(huì)多出 /debug/pprof 的 endpoint 可用于觀察應(yīng)用程序的情況

分析

一、通過(guò) Web 界面

查看當(dāng)前總覽:訪問 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

這個(gè)頁(yè)面中有許多子頁(yè)面,咱們繼續(xù)深究下去,看看可以得到什么?

  • cpu(CPU Profiling): $HOST/debug/pprof/profile,默認(rèn)進(jìn)行 30s 的 CPU Profiling,得到一個(gè)分析用的 profile 文件
  • block(Block Profiling):$HOST/debug/pprof/block,查看導(dǎo)致阻塞同步的堆棧跟蹤
  • goroutine:$HOST/debug/pprof/goroutine,查看當(dāng)前所有運(yùn)行的 goroutines 堆棧跟蹤
  • heap(Memory Profiling): $HOST/debug/pprof/heap,查看活動(dòng)對(duì)象的內(nèi)存分配情況
  • mutex(Mutex Profiling):$HOST/debug/pprof/mutex,查看導(dǎo)致互斥鎖的競(jìng)爭(zhēng)持有者的堆棧跟蹤
  • threadcreate:$HOST/debug/pprof/threadcreate,查看創(chuàng)建新OS線程的堆棧跟蹤

二、通過(guò)交互式終端使用

(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 profile in /Users/eddycjy/pprof/pprof.samples.cpu.007.pb.gz
Type: cpu
Duration: 1mins, Total samples = 26.55s (44.15%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) 

執(zhí)行該命令后,需等待 60 秒(可調(diào)整 seconds 的值),pprof 會(huì)進(jìn)行 CPU Profiling。結(jié)束后將默認(rèn)進(jìn)入 pprof 的交互式命令模式,可以對(duì)分析的結(jié)果進(jìn)行查看或?qū)С觥>唧w可執(zhí)行 pprof help 查看命令說(shuō)明

(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:給定函數(shù)上運(yùn)行耗時(shí)
  • flat%:同上的 CPU 運(yùn)行耗時(shí)總比例
  • sum%:給定函數(shù)累積使用 CPU 總比例
  • cum:當(dāng)前函數(shù)加上它之上的調(diào)用運(yùn)行總耗時(shí)
  • cum%:同上的 CPU 運(yùn)行耗時(shí)總比例

最后一列為函數(shù)名稱,在大多數(shù)的情況下,我們可以通過(guò)這五列得出一個(gè)應(yīng)用程序的運(yùn)行情況,加以優(yōu)化 ??

(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 profile in /Users/eddycjy/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.008.pb.gz
Type: inuse_space
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 837.48MB, 100% of 837.48MB total
      flat  flat%   sum%        cum   cum%
  837.48MB   100%   100%   837.48MB   100%  main.main.func1
  • -inuse_space:分析應(yīng)用程序的常駐內(nèi)存占用情況

  • -alloc_objects:分析應(yīng)用程序的內(nèi)存臨時(shí)分配情況

(3) go tool pprof http://localhost:6060/debug/pprof/block

(4) go tool pprof http://localhost:6060/debug/pprof/mutex

三、PProf 可視化界面

這是令人期待的一小節(jié)。在這之前,我們需要簡(jiǎn)單的編寫好測(cè)試用例來(lái)跑一下

編寫測(cè)試用例

(1)新建 data/d_test.go,文件內(nèi)容:

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í)行測(cè)試用例

$ go test -bench=. -cpuprofile=cpu.prof
pkg: github.com/EDDYCJY/go-pprof-example/data
BenchmarkAdd-4      10000000           187 ns/op
PASS
ok      github.com/EDDYCJY/go-pprof-example/data    2.300s

-memprofile 也可以了解一下

啟動(dòng) PProf 可視化界面
方法一:
$ go tool pprof -http=:8080 cpu.prof
方法二:
$ go tool pprof cpu.prof 
$ (pprof) web

如果出現(xiàn) Could not execute dot; may need to install graphviz.,就是提示你要安裝 graphviz 了 (請(qǐng)右拐谷歌)

查看 PProf 可視化界面

(1)Top

image

(2)Graph

image

框越大,線越粗代表它占用的時(shí)間越大哦

(3)Peek

image

(4)Source

image

通過(guò) PProf 的可視化界面,我們能夠更方便、更直觀的看到 Go 應(yīng)用程序的調(diào)用鏈、使用情況等,并且在 View 菜單欄中,還支持如上多種方式的切換

你想想,在煩惱不知道什么問題的時(shí)候,能用這些輔助工具來(lái)檢測(cè)問題,是不是瞬間效率翻倍了呢 ??

四、PProf 火焰圖

另一種可視化數(shù)據(jù)的方法是火焰圖,需手動(dòng)安裝原生 PProf 工具:

(1) 安裝 PProf

$ go get -u github.com/google/pprof

(2) 啟動(dòng) PProf 可視化界面:

$ pprof -http=:8080 cpu.prof

(3) 查看 PProf 可視化界面

打開 PProf 的可視化界面時(shí),你會(huì)明顯發(fā)現(xiàn)比官方工具鏈的 PProf 精致一些,并且多了 Flame Graph(火焰圖)

它就是本次的目標(biāo)之一,它的最大優(yōu)點(diǎn)是動(dòng)態(tài)的。調(diào)用順序由上到下(A -> B -> C -> D),每一塊代表一個(gè)函數(shù),越大代表占用 CPU 的時(shí)間更長(zhǎng)。同時(shí)它也支持點(diǎn)擊塊深入進(jìn)行分析!

image

總結(jié)

在本章節(jié),粗略地介紹了 Go 的性能利器 PProf。在特定的場(chǎng)景中,PProf 給定位、剖析問題帶了極大的幫助

希望本文對(duì)你有所幫助,另外建議能夠自己實(shí)際操作一遍,最好是可以深入琢磨一下,內(nèi)含大量的用法、知識(shí)點(diǎn) ??

思考題

你很優(yōu)秀的看到了最后,那么有兩道簡(jiǎn)單的思考題,希望拓展你的思路

(1)flat 一定大于 cum 嗎,為什么?什么場(chǎng)景下 cum 會(huì)比 flat 大?

(2)本章節(jié)的 demo 代碼,有什么性能問題?怎么解決它?

來(lái),曬出你的想法!??


原文地址:Golang 大殺器之性能剖析 PProf

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評(píng)論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,727評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,411評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,777評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,978評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,216評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,657評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,960評(píng)論 2 373

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