接着上次的博客: https://www.cnblogs.com/ITPower/articles/12315637.html
pprof的基本操作, 上次博客有記錄, 這里進一步研究pprof
接下來開始今天的學習內容. 計划今天研究以下幾個部分的內容
1. pprof擴展
a. 在單元測試testing.B中測試檢測程序的性能
b. web項目中檢測程序的性能
2. pprof的使用, 以及如何看生成的svg圖.
3. 使用pprof分析近期做過的一個beego項目. 詳見另一篇博客: https://www.cnblogs.com/ITPower/articles/12324659.html
4. 調研pprof是否能夠使用在生成環境.
5. 研究testing.T, testing.B testing.TB testing.N的區別: 詳見博客https://www.cnblogs.com/ITPower/articles/12320577.html
一. pprof擴展
Go語言自帶了強大的性能測試工具pprof,位於 net/http 包下的 pprof, 官方文檔
go中有pprof包來做代碼的性能監控,在兩個地方有包:net/http/pprof 和 runtime/pprof
其實net/http/pprof中只是使用runtime/pprof包來進行封裝了一下,並在http端口上暴露出來.
- net/http/pprof : 可以做到直接看到當前 web 服務的狀態,包括 CPU 占用情況和內存使用情況等。如果服務是一直運行的,如 web 應用,可以很方便的使用第一種方式 import "net/http/pprof"。
- runtime/pprof : 可以用來產生 dump 文件,再使用 Go Tool PProf 來分析這運行日志。
我們研究pprof的使用從兩個方面研究 :
1. 如何查看單元測試中對性能的測試分析
2. 查看web服務的性能
1. 查看單元測試中對性能的測試分析
我們借用上一次的一個例子. 對異常處理的代碼部分進行性能分析
第一步: 寫性能分析的測試用例.
比如: 我們模擬用戶錯誤的輸出情況
func BenchmarkWrapError(t *testing.B) { h := handlerUserError code := 400 message := "user error" for i := 0; i < t.N ; i ++ { f := WrapError(h) // 模擬Request和response response := httptest.NewRecorder() request := httptest.NewRequest(http.MethodGet, "http://www.baidu.com", nil) f(response, request) //讀取reponse返回的body b, _ := ioutil.ReadAll(response.Body) body := strings.Trim(string(b), "\n") if code != response.Code || message != body { t.Errorf("except--code: %d, message: %s \n actual--code:%d, message:%s", code, message, response.Code, body) } } }
第二步: 進入到文件目錄, 在命令行執行 go test -bench . -cpuprofile cpu.out 性能測試cpu的消耗情況
go test -bench . -cpuprofile cpu.out
第三步: 執行pprof分析
go tool pprof cpu.out
第四步: 輸入web, 會生成一個svg的文件, 然后使用瀏覽器查看視圖.
從圖中可以看出每一步花費的時間大概是多少. 其中哪一個步驟花費的時間最長. 然后我們就可以針對其進行優化了
備注: 要想以web視圖的方式查看上述結果, 需要下載graphviz, 下載方式參考https://www.cnblogs.com/ITPower/articles/12315637.html的第四點, 附截圖
2. 查看web服務的性能
第一步: import 增加net/http/pprof包
import( _ net/http/pprof )
第二步: 打開http端的監聽端口
go func() { http.ListenAndServe("localhost:8888", nil) }()
第三步: 在網頁上查看, 輸入http://localhost:8888/debug/profile, 這是會看到如下頁面
這個頁面分為兩部分. 第一部分是當前服務的使用情況. 第二部分, 對命令的解析
使用情況截圖如下
Count 表示當前服務使用數, 比如2, 是消耗內存的進程數. 21表示線程創建數, 2 表示歷史數據. 等等
Profile 是性能指標名
命令說明如下:
- allocs: 過去所有內存分配的樣本
- block: 堆棧導致對原始同步的阻塞
- cmline: 當前程序的命令行調用
- goroutine: 當前所有goroutine的堆棧跟蹤
- heap: 活動對象內存分配的采樣。您可以指定gc GET參數以在獲取堆樣本之前運行GC。
- mutex: 競爭互斥持有人的堆棧痕跡
- profile: CPU配置文件。您可以在GET參數中指定持續時間。獲取概要文件后,請使用go tool pprof命令調查文件。
- threadcreate: 導致創建新OS線程的堆棧跟蹤
- trace: 當前程序執行的痕跡。您可以在GET參數中指定持續時間。獲取跟蹤文件后,使用go工具trace命令調查跟蹤。
第四步: 通過Graphviz, 查看heap
從圖中看, cpu的使用是0, heap的使用是2, 所以, 我們查看heap.
go tool pprof http://127.0.0.1:8888/debug/pprof/heap
接下來我們可以通過help 查看pprof都有哪些命令. 常用的命令有. tree, top, web
我們用tree查看內存的使用情況
還可以使用top查看最消耗內存的地方
接下來還是使用web查看視圖
視圖更加直觀, 哪一步消耗了多少內存
第五步: 模擬並發, 測試性能
這樣的程序都是剛剛運行, 所以內存消耗, cpu消耗都比較少. 接下來我們模擬大量請求, 試一試性能如何
1. 下載一個模擬http請求的工具wrk(模擬現實, 了解系統瓶頸, 將服務器置於一個繁忙的狀態, 就像生產環境一樣. ), 下載地址: https://github.com/wg/wrk.git
在github上也有這個工具的介紹,
git clonehttps://github.com/wg/wrk.git cd wrk make
備注: 整個操作參考github上的說明即可.
2. 安裝好wrk以后, 模擬批量請求
./wrk -c400 -t8 -d5m http://localhost:8899/v1/user/login
我模擬的是批量登錄, 參數含義如下
- -c400: 我們有400個連接可以保持打開狀態
-t8
:意味着我們使用8個線程來構建請求-d5m
表示測試時間將持續5分鍾
3. 在瀏覽器輸入
http://localhost:8899/debug/pprof/
查看使用情況
4. awk執行完以后, 查看執行結果匯總
5. 接下來用go tool pprof 查看 heap
go tool pprof -alloc_space/-inuse_space
http://localhost:8899/debug/pprof/heap
-
-alloc_space: 過去使用的內存數據
-
-inuse_space: 正在使用的內存數據
返回的視圖
方框越大, 表示內存消耗越多.
參考文獻:
1. https://blog.csdn.net/guyan0319/article/details/85007181