Go程序性能分析方法(一文全解)

前言

golang作爲一門高效的語言,性能監控和調試非常重要,如何進行性能監控和分析是優化的關鍵。

Go語言項目中的性能優化主要有以下幾個方面:

  • CPU profile:報告程序的 CPU 使用情況,按照一定頻率去採集應用程序在 CPU 和寄存器上面的數據
  • Memory Profile(Heap Profile):報告程序的內存使用情況
  • Block Profiling:報告 goroutines 不在運行狀態的情況,可以用來分析和查找死鎖等性能瓶頸
  • Goroutine Profiling:報告 goroutines 的使用情況,有哪些 goroutine,它們的調用關係是怎樣的

go語言提供包

  • runtime/pprof:採集工具型應用運行數據進行分析
  • net/http/pprof:採集服務型應用運行時數據進行分析

採集方式

pprof開啓後,每隔一段時間(10ms)就會收集下當前的堆棧信息,獲取格格函數佔用的CPU以及內存資源;最後通過對這些採樣數據進行分析,形成一個性能分析報告。
引入包

import "runtime/pprof"

使用方法

pprof.StartCPUProfile(w io.Writer) //開啓,向一個io中寫入cpu信息
pprof.WriteHeapProfile(w io.Writer) //向一個io中寫入內存信息
pprof.StopCPUProfile() //停止,寫入完成

命令模式

將數據寫入到文件中
通過 go tool pprof [文件名] 命令查看使用

我們可以在交互界面輸入top3來查看程序中佔用CPU前3位的函數:
在這裏插入圖片描述
其中:

  • flat:當前函數佔用CPU的耗時
  • flat%:當前函數佔用CPU的耗時百分比
  • sun%:函數佔用CPU的耗時累計百分比
  • cum:當前函數加上調用當前函數的函數佔用CPU的總耗時
  • cum%:當前函數加上調用當前函數的函數佔用CPU的總耗時百分比
  • 最後一列:函數名稱

也可以通過list 函數名查看函數的信息
在這裏插入圖片描述
通過分析發現大部分CPU資源被26行佔用

調度圖

輸入web在網頁中查看調度圖,輸入pdf生成一個pdf文件
需要安裝工具graphviz
在這裏插入圖片描述
關於圖形的說明: 每個框代表一個函數,理論上框的越大表示佔用的CPU資源越多。 方框之間的線條代表函數之間的調用關係。 線條上的數字表示函數調用的次數。 方框中的第一行數字表示當前函數佔用CPU的百分比,第二行數字表示當前函數累計佔用CPU的百分比。

go tool pprof默認是使用-inuse_space進行統計,還可以使用-inuse-objects查看分配對象的數量。

監控方式

如果你的應用程序是一直運行的,比如 web 應用,那麼可以使用net/http/pprof庫,它能夠在提供 HTTP 服務進行分析。

如果使用了默認的http.DefaultServeMux(通常是代碼直接使用 http.ListenAndServe(“0.0.0.0:8000”, nil)),只需要在你的web server端代碼中按如下方式導入net/http/pprof

import _ "net/http/pprof"

如果你使用自定義的 Mux,則需要手動註冊一些路由規則:

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

如果你使用的是gin框架,那麼推薦使用"github.com/DeanThompson/ginpprof"。

不管哪種方式,你的 HTTP 服務都會多出/debug/pprof endpoint,訪問它會得到類似下面的內容:
在這裏插入圖片描述
這個路徑下還有幾個子頁面:

  • /debug/pprof/profile:訪問這個鏈接會自動進行 CPU profiling,持續 30s,並生成一個文件供下載
  • /debug/pprof/heap: Memory Profiling 的路徑,訪問這個鏈接會得到一個內存 Profiling 結果的文件
  • /debug/pprof/block:block Profiling 的路徑
  • /debug/pprof/goroutines:運行的 goroutines 列表,以及調用關係

go-torch方法

火焰圖(Flame Graph)是 Bredan Gregg 創建的一種性能分析圖表,因爲它的樣子近似 🔥而得名。上面的 profiling 結果也轉換成火焰圖,如果對火焰圖比較瞭解可以手動來操作,不過這裏我們要介紹一個工具:go-torch。這是 uber 開源的一個工具,可以直接讀取 golang profiling 數據,並生成一個火焰圖的 svg 文件。
安裝

 go get -v github.com/uber/go-torch

火焰圖 svg 文件可以通過瀏覽器打開,它對於調用圖的最優點是它是動態的:可以通過點擊每個方塊來 zoom in 分析它上面的內容。

火焰圖的調用順序從下到上,每個方塊代表一個函數,它上面一層表示這個函數會調用哪些函數,方塊的大小代表了佔用 CPU 使用的長短。火焰圖的配色並沒有特殊的意義,默認的紅、黃配色是爲了更像火焰而已。

go-torch 工具的使用非常簡單,沒有任何參數的話,它會嘗試從http://localhost:8080/debug/pprof/profile獲取 profiling 數據。它有三個常用的參數可以調整:

-u –url:要訪問的 URL,這裏只是主機和端口部分
-s –suffix:pprof profile 的路徑,默認爲 /debug/pprof/profile
–seconds:要執行 profiling 的時間長度,默認爲 30s

FlameGraph工具

要生成火焰圖,需要事先安裝 FlameGraph工具,這個工具的安裝很簡單(需要perl環境支持),只要把對應的可執行文件加入到環境變量中即可。

  1. 下載安裝perl:https://www.perl.org/get.html
  2. 下載FlameGraph:git clone https://github.com/brendangregg/FlameGraph.git
  3. 將FlameGraph目錄加入到操作系統的環境變量中。
  4. Windows平臺的同學,需要把go-torch/render/flamegraph.go文件中的GenerateFlameGraph按如下方式修改,然後在go-torch目錄下執行go install即可。go-torch命令就是調用這個生成的文件,最好給bin目錄配置環境變量
// GenerateFlameGraph runs the flamegraph script to generate a flame graph SVG. func GenerateFlameGraph(graphInput []byte, args ...string) ([]byte, error) {
flameGraph := findInPath(flameGraphScripts)
if flameGraph == "" {
	return nil, errNoPerlScript
}
if runtime.GOOS == "windows" {
	return runScript("perl", append([]string{flameGraph}, args...), graphInput)
}
  return runScript(flameGraph, args, graphInput)
}

wrk壓測工具(go-wrk)

推薦使用https://github.com/wg/wrkhttps://github.com/adjust/go-wrk

go-torch使用

啓動需要監控的程序,運行wrk壓測,在終端中執行命令,30s後會在當前目錄生成 torch.svg 文件

go-torch -u http://127.0.0.1:8080 -t 30

用瀏覽器打開這個文件,如下圖
在這裏插入圖片描述
這裏是一個典型失敗的案例,任何性能測試分析,必須要在高壓環境下才有意義,如下圖。
在這裏插入圖片描述
火焰圖的y軸表示cpu調用方法的先後,x軸表示在每個採樣調用時間內,方法所佔的時間百分比,越寬代表佔據cpu時間越多。通過火焰圖我們就可以更清楚的找出耗時長的函數調用,然後不斷的修正代碼,重新採樣,不斷優化
當然,go-torch也能夠對內存進行監控,只需要在命令的最後面添加,
–colors=mem
效果圖如下
在這裏插入圖片描述

Metricbeat 監控

除了上面的方法外,我們還能夠開啓自定義監控
使用expvar包

import "expvar"

expvar包的具體用法可以參考官網的文檔,這裏就不細講了。
使用expvar包監控就不能向上面兩種一樣簡單方便了,需要我們自己結果數據的顯示問題,網上的常用方法是使用elastic家族的三大件
Metricbeat + ElasticSearch + Kibana
效果非常的漂亮
在這裏插入圖片描述
elastic家族系列下載地址:https://www.elastic.co/cn/
這裏貼出使用方法:https://www.cnblogs.com/mrblue/archive/2019/05.html
可惜可芭納只有英文的,使用很是費勁,且吾能力有限,不懂破解,只能望而興嘆。

自定義方法

這裏介紹一種吾藉助expvar包實現的監控方法。吾對前端實在一無所知,故界面很low,還是藉助模板做出來的,本想直接將json傳到前端,怎奈,吾前端能力有限,嗚呼哀哉~~~

只需要導入包

import "gitee.com/yutiandou/wdtools/wdsys"

再執行下面的方法就可以了(自動進入協程中執行),

  • 第一個參數是地址端口
  • 第二個參數是 間隔多長時間掃描系統,如果是發佈的程序最好去掉監控或者將時間設長點。
wdsys.StartMonitoringToHttp(":8000", time.Second*3)

這樣會自動採集數據,並保留最近10條數據,可以通過url:/debug訪問,如下圖
在這裏插入圖片描述
在這裏插入圖片描述
我只實現了常用的十幾種數據顯示,如電腦內存使用情況,堆棧信息,gc情況,下圖中的是還沒實現了。需要查看這些數據的童鞋,可以自己實現一下,當做娛樂消遣。
在這裏插入圖片描述
除了上面的信息外,還可以藉助工具包中的其他函數,獲取系統其他信息。如下截圖。
在這裏插入圖片描述
通過上面的6個api可以拉取系統的
本地ip地址,Cpu使用率,邏輯盒數,cpu負載,系統磁盤的分區信息,系統軟硬件信息和下圖
在這裏插入圖片描述
更多wdtools包使用方法參考吾之碼雲:https://gitee.com/yutiandou/wdtools

未完待續。。。。。。

發佈了53 篇原創文章 · 獲贊 5 · 訪問量 4020
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章