> Go語言內置了獲取程序的運行數據的工具,包括以下兩個標準庫:
** runtime/pprof:采集工具型應用運行數據進行分析
** net/http/pprof:采集服務型應用運行時數據進行分析
> pprof開啟后,每隔一段時間(10ms)就會收集下當前的堆棧信息,獲取各個函數占用的CPU以及內存資源;最后通過對這些采樣數據進行分析,形成一個性能分析報告
> 注意,我們只應該在性能測試的時候才在代碼中引入pprof。
[TOC]
## 工具型應用
> 如果你的應用程序是運行一段時間就結束退出類型,可以使用`runtime/pprof庫`進行測試
### 測試程序 (test.go)
~~~
package main
import (
"fmt"
"os"
"runtime/pprof"
"time"
)
// 一段有問題的代碼
func logicCode() {
var c chan int
for {
select {
case v := <-c:
fmt.Printf("recv from chan, value:%v\n", v)
default:
}
}
}
func main() {
// CPU 性能測試
file, err := os.Create("./cpu.pprof")
if err != nil {
fmt.Printf("create cpu pprof failed, err:%v\n", err)
return
}
pprof.StartCPUProfile(file)
defer pprof.StopCPUProfile()
for i := 0; i < 8; i++ {
go logicCode()
}
time.Sleep(20 * time.Second)
// Mem 性能測試
file2, err2 := os.Create("./mem.pprof")
if err != nil {
fmt.Printf("create mem pprof failed, err:%v\n", err2)
return
}
pprof.WriteHeapProfile(file2)
file.Close()
}
~~~
> 程序執行后,等待30秒后會在當前目錄下生成一個`cpu.pprof`文件
### 解析分析報告
~~~
go tool pprof cpu.pprof
~~~
> 執行上面的代碼會進入交互界面,輸入`top3`來查看程序中占用CPU前3位的函數
~~~
top3
~~~
> 其中:
* flat:當前函數占用CPU的耗時
* flat::當前函數占用CPU的耗時百分比
* sun%:函數占用CPU的耗時累計百分比
* cum:當前函數加上調用當前函數的函數占用CPU的總耗時
* cum%:當前函數加上調用當前函數的函數占用CPU的總耗時百分比
* 最后一列:函數名稱
> 我們還可以使用`list命令`查看具體的函數分析,例如執行`list logicCode`查看我們編寫的函數的詳細分析
~~~
list logicCode
~~~
### 圖形化分析報告
> 需要安裝`graphviz`工具
> 下載地址:https://graphviz.org/download/,linux安裝使用 `yum install graphviz`
~~~
go tool pprof --pdf cpu.pprof
~~~
## 服務型應用
> 如果你的應用程序是一直運行的,比如web應用,那么可以使用`net/http/pprof庫`,它能夠在提供 HTTP 服務進行分析
### web服務引如pprof
~~~
package main
import (
"github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
pprof.Register(router)
...
router.Run(":8080")
}
~~~
### 訪問性能測試web頁面
> 地址:http://localhost:8080/debug/pprof/

* /debug/pprof/profile:訪問這個鏈接會自動進行 CPU profiling,持續 30s,并生成一個文件供下載
* /debug/pprof/heap: Memory Profiling 的路徑,訪問這個鏈接會得到一個內存 Profiling 結果的文件
* /debug/pprof/block:block Profiling 的路徑
* /debug/pprof/goroutines:運行的 goroutines 列表,以及調用關系
### 編寫測試代碼
> 路徑:/test/request_test.go
~~~
package test
import (
"fmt"
"io/ioutil"
"net/http"
"testing"
)
// 向web接口請求,用于收集cpu占用情況。
func TestPprof(t *testing.T) {
for i := 1; i <= 500; i++ {
resp, _ := http.Get("http://localhost:8080/pro/test")
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
}
~~~
### 生成測試報告
> 點擊`測試web頁面`中的`profile`,進行cpu上的測試,點擊后30s后會生成測試文件,在此期間快速的模擬訪問,可執行以下腳本
~~~
go test test/request_test.go
~~~
> 最后會生成`profile`文件供下載,將其拷貝到項目中,并進行分析報告
### 解析分析報告
~~~
go tool pprof profile
~~~
> 執行上面的代碼會進入交互界面,輸入`top3`來查看程序中占用CPU前3位的函數
~~~
top3
~~~
> 其中:
* flat:當前函數占用CPU的耗時
* flat::當前函數占用CPU的耗時百分比
* sun%:函數占用CPU的耗時累計百分比
* cum:當前函數加上調用當前函數的函數占用CPU的總耗時
* cum%:當前函數加上調用當前函數的函數占用CPU的總耗時百分比
* 最后一列:函數名稱
> 我們還可以使用`list命令`查看具體的函數分析,例如執行`list logicCode`查看我們編寫的函數的詳細分析
~~~
list logicCode
~~~
### 圖形化分析報告
> 需要安裝`graphviz`工具
> 下載地址:https://graphviz.org/download/,linux安裝使用 `yum install graphviz`
~~~
go tool pprof --pdf profile
~~~

> 參考文章:https://www.liwenzhou.com/posts/Go/performance_optimisation/
- 基礎知識
- 開發環境
- 包名規則
- 包初始化 (init)
- 基礎數據類型
- 基礎類型轉換
- 格式化輸出
- go指針
- 流程控制語句
- 函數定義
- 匿名函數
- 數組和切片
- map集合
- 結構體
- Interface接口
- 日期處理
- 數學計算
- 正則表達式
- 協程 (并發處理)
- channel
- waitgroup
- mutex (鎖機制)
- websocket
- protobuf
- Redis
- 錯誤處理
- 打包程序
- NSQ消息隊列
- 單元測試
- beego
- 安裝入門
- Gin
- 快速入門
- 路由與控制器
- 處理請求參數
- 表單驗證
- 處理響應結果
- 渲染HTML模版
- 訪問靜態文件
- Gin中間件
- Cookie處理
- Session處理
- Gin上傳文件
- swagger
- pprof性能測試
- GORM
- 入門教程
- 模型定義
- 數據庫連接
- 插入數據
- 查詢數據
- 更新數據
- 刪除數據
- 事務處理
- 關聯查詢
- 屬于 (BELONG TO)
- 一對一 (Has One)
- 一對多 (Has Many)
- 多對多 (Many to Many)
- 預加載 (Preloading)
- 錯誤處理
- 第三方常用插件
- viper 讀取配置文件
- zap 高性能日志
- Nginx代理配置
- Goland 快捷鍵