go 性能監(jiān)控神器

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

前言

寫(xiě)了幾噸代碼,實(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)用棧,是很常見(jiàn)的 stacktrace 配置文件格式

支持什么使用模式

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

可以做什么

  • CPU Profiling:CPU 分析,按照一定的頻率采集所監(jiān)聽(tīng)的應(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)單的例子

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

編寫(xiě) 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)前總覽:訪問(wèn) 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ū)С?。具體可執(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)單的編寫(xiě)好測(cè)試用例來(lái)跑一下

編寫(xiě)測(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 菜單欄中,還支持如上多種方式的切換

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

四、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 可視化界面

打開(kāi) 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 給定位、剖析問(wèn)題帶了極大的幫助

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

思考題

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

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

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

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

作者:EDDYCJY
鏈接:http://www.itdecent.cn/p/4e4ff6be6af9
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容