[TOC]
go中提供了pprof包來做代碼的性能監控,在兩個地方有包:
* net/http/pprof
* runtime/pprof
其實net/http/pprof中只是使用runtime/pprof包來進行封裝了一下,并在http端口上暴露出來
~~~
#web服務器:
import (
"net/http"
_ "net/http/pprof"
)
#一般應用程序(實際應用無web交互)
import (
"net/http"
_ "runtime/pprof"
)
~~~
# 使用 net/http/pprof 做WEB服務器的性能監控
如果你的go程序是用http包啟動的web服務器,想要查看自己的web服務器的狀態。這個時候就可以選擇net/http/pprof。
~~~
import _ "net/http/pprof"
~~~
然后就可以在瀏覽器中使用http://localhost:port/debug/pprof/ 直接看到當前web服務的狀態,包括CPU占用情況和內存使用情況等。
當然,非WEB的也可以用下面方式啟動WEB。
在 main 方法中增加
~~~
func main() {
??? go func() {
??????? http.ListenAndServe("localhost:6060", nil)
??? }()
~~~

# CPU消耗分析
**使用 runtime/pprof 做應用程序性能監控**
關鍵代碼:
~~~
import? "runtime/pprof"
func main() {
??? f, err := os.OpenFile("./tmp/cpu.prof", os.O_RDWR|os.O_CREATE, 0644)
??? if err != nil {
??????? log.Fatal(err)
??? }
??? defer f.Close()
??? pprof.StartCPUProfile(f)
??? defer pprof.StopCPUProfile()
~~~
注意,有時候 defer f.Close(), defer pprof.StopCPUProfile() 會執行不到,這時候我們就會看到 prof 文件是空的, 我們需要在自己代碼退出的地方,增加上下面兩行,確保寫文件內容了。
~~~
pprof.StopCPUProfile()
f.Close()
~~~
# 對產生的文件進行分析:
我們可以使用 go tool pprof (應用程序) (應用程序的prof文件) 方式來對這個 prof 文件進行分析。
~~~
$ go tool pprof HuaRongDao ./tmp/cpu.prof
Entering interactive mode (type "help" for commands)
(pprof)
~~~
一些常用 pprof 的命令:
# top
在默認情況下,top命令會輸出以本地取樣計數為順序的列表。我們可以把這個列表叫做本地取樣計數排名列表。
~~~
(pprof) top
2700ms of 3200ms total (84.38%)
Dropped 58 nodes (cum <= 16ms)
Showing top 10 nodes out of 111 (cum >= 80ms)
????? flat? flat%?? sum%??????? cum?? cum%
???? 670ms 20.94% 20.94%????? 670ms 20.94%? runtime.mach\_semaphore\_signal
???? 580ms 18.12% 39.06%????? 590ms 18.44%? runtime.cgocall
???? 370ms 11.56% 50.62%????? 370ms 11.56%? runtime.mach\_semaphore\_wait
???? 360ms 11.25% 61.88%????? 360ms 11.25%? runtime.memmove
???? 210ms? 6.56% 68.44%????? 580ms 18.12%? golang.org/x/mobile/gl.(\*context).DoWork
???? 120ms? 3.75% 72.19%????? 120ms? 3.75%? runtime.usleep
???? 110ms? 3.44% 75.62%????? 110ms? 3.44%? image/png.filterPaeth
???? 100ms? 3.12% 78.75%????? 160ms? 5.00%? compress/flate.(\*decompressor).huffSym
???? 100ms? 3.12% 81.88%????? 100ms? 3.12%? image/draw.drawNRGBASrc
????? 80ms? 2.50% 84.38%?????? 80ms? 2.50%? runtime.memclr
(pprof)
~~~
參考:[https://github.com/hyper-carrot/go\_command\_tutorial/blob/master/0.12.md](https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md "https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md")?
默認情況下top命令會列出前10項內容。但是如果在top命令后面緊跟一個數字,那么其列出的項數就會與這個數字相同
# web
與gv命令類似,web命令也會用圖形化的方式來顯示概要文件。但不同的是,web命令是在一個Web瀏覽器中顯示它。如果你的Web瀏覽器已經啟動,那么它的顯示速度會非常快。如果想改變所使用的Web瀏覽器,可以在Linux下設置符號鏈接/etc/alternatives/gnome-www-browser或/etc/alternatives/x-www-browser,或在OS X下改變SVG文件的關聯Finder。
mac 下 修改默認打開方式: 右鍵一個想處理的文件,按alt 鍵(lion)出現always open with,然后打開,整個過程中, 先右鍵,然后一直按 alt, 一直到打開為止

參考資料:
go tool pprof
[https://github.com/hyper-carrot/go\_command\_tutorial/blob/master/0.12.md](https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md "https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md")?
Go的pprof使用
[http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html](http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html "http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html")?
Profiling Go Programs
[https://blog.golang.org/profiling-go-programs](https://blog.golang.org/profiling-go-programs "https://blog.golang.org/profiling-go-programs")
# 內存泄漏或消耗分析
關鍵代碼
~~~
fm, err := os.OpenFile("./tmp/mem.out", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
??? log.Fatal(err)
}
pprof.WriteHeapProfile(fm)
fm.Close()
~~~
在我們需要生成當時的內存情況時,只需要執行上面代碼即可。
觸發的條件可以通過 http 的一個接口,或者退出時,或者接收到某個特殊信號,這些邏輯就需要自己實現了。
分析方法,跟之上CPU的分析方法一致

\[golang\]內存不斷增長bytes.makeSlice
[http://studygolang.com/articles/2763](http://studygolang.com/articles/2763 "http://studygolang.com/articles/2763")
# graphviz可視化
下面是一個使用pprof長時間運行的例子:

pprof能夠借助grapgviz產生程序的調用圖。默認情況下pprof基于對程序的30秒采樣產生調用圖。
* 圖中的連線代表對方法的調用, 連線上的標簽代表指定的方法調用的采樣值(譯者注:go tool pprof顯示的是調用時間)。
* 方框的大小與方法運行的采樣值的大小有關。
* 每個方框由兩個標簽:一個是方法運行的時間占比,一個是它在采樣的堆棧中出現的時間占比(譯者注: 前者你可以看成flat時間,后者看成cumulate時間)
**在Mac上安裝工具**:
~~~
brew install gperftools$ brew install graphviz
~~~
~~~
pprof --web localhost:6060/debug
~~~
我并沒有使用上面的工具,因為Go開發環境已經集成了pprof工具,所以你不需要安裝gperftools工具,而且使用的命令和上面的命令不一樣。
當然graphviz是必裝的。
你可以通過下面的命令采集30s的數據并生成SVG調用圖:
~~~
go tool pprof -web http://127.0.0.1:6060/debug/pprof/profile
~~~
Heap profile:
~~~
go tool pprof --text http://localhost:8080/debug/pprof/heap
~~~
CPU profile:
~~~
go tool pprof --text http://localhost:8080/debug/pprof/profile
~~~
Goroutine blocking profile:
~~~
go tool pprof --text http://localhost:8080/debug/pprof/block
~~~
# go-torch
和pprof一樣,它也采用30秒的采樣數據生成火焰圖。
* 棧幀(Stack frame,調用鏈)垂直堆疊,顯示棧的深度
* 幀的寬度代表一個方法的運行的時間占比
* 如果一個方法被調用者調用,它會顯示多次,分列在不同的調用者的堆棧上。(譯者注:這點和pprof工具不同,pprof至顯示一個方法的框,上面的時間標簽是所有的調用者調用的時間)
* 顏色是任意的(arbitrary), 橫坐標根據字母順序排列
需要安裝go-torch工具和brandangregg的火焰圖生成腳本:
~~~
go get github.com/uber/go-torch
git clone git@github.com:brendangregg/FlameGraph.git
export PATH-$PATH:/path/to/FlameGraph
go-torch --file "torch.svg" --url http://localhost:6060
~~~
- 基礎
- 簡介
- 主要特征
- 變量和常量
- 編碼轉換
- 數組
- byte與rune
- big
- sort接口
- 和mysql類型對應
- 函數
- 閉包
- 工作區
- 復合類型
- 指針
- 切片
- map
- 結構體
- sync.Map
- 隨機數
- 面向對象
- 匿名組合
- 方法
- 接口
- 權限
- 類型查詢
- 異常處理
- error
- panic
- recover
- 自定義錯誤
- 字符串處理
- 正則表達式
- json
- 文件操作
- os
- 文件讀寫
- 目錄
- bufio
- ioutil
- gob
- 棧幀的內存布局
- shell
- 時間處理
- time詳情
- time使用
- new和make的區別
- container
- list
- heap
- ring
- 測試
- 單元測試
- Mock依賴
- delve
- 命令
- TestMain
- path和filepath包
- log日志
- 反射
- 詳解
- plugin包
- 信號
- goto
- 協程
- 簡介
- 創建
- 協程退出
- runtime
- channel
- select
- 死鎖
- 互斥鎖
- 讀寫鎖
- 條件變量
- 嵌套
- 計算單個協程占用內存
- 執行規則
- 原子操作
- WaitGroup
- 定時器
- 對象池
- sync.once
- 網絡編程
- 分層模型
- socket
- tcp
- udp
- 服務端
- 客戶端
- 并發服務器
- Http
- 簡介
- http服務器
- http客戶端
- 爬蟲
- 平滑重啟
- context
- httptest
- 優雅中止
- web服務平滑重啟
- beego
- 安裝
- 路由器
- orm
- 單表增刪改查
- 多級表
- orm使用
- 高級查詢
- 關系查詢
- SQL查詢
- 元數據二次定義
- 控制器
- 參數解析
- 過濾器
- 數據輸出
- 表單數據驗證
- 錯誤處理
- 日志
- 模塊
- cache
- task
- 調試模塊
- config
- 部署
- 一些包
- gjson
- goredis
- collection
- sjson
- redigo
- aliyunoss
- 密碼
- 對稱加密
- 非對稱加密
- 單向散列函數
- 消息認證
- 數字簽名
- mysql優化
- 常見錯誤
- go run的錯誤
- 新手常見錯誤
- 中級錯誤
- 高級錯誤
- 常用工具
- 協程-泄露
- go env
- gometalinter代碼檢查
- go build
- go clean
- go test
- 包管理器
- go mod
- gopm
- go fmt
- pprof
- 提高編譯
- go get
- 代理
- 其他的知識
- go內存對齊
- 細節總結
- nginx路由匹配
- 一些博客
- redis為什么快
- cpu高速緩存
- 常用命令
- Go 永久阻塞的方法
- 常用技巧
- 密碼加密解密
- for 循環迭代變量
- 備注
- 垃圾回收
- 協程和纖程
- tar-gz
- 紅包算法
- 解決golang.org/x 下載失敗
- 逃逸分析
- docker
- 鏡像
- 容器
- 數據卷
- 網絡管理
- 網絡模式
- dockerfile
- docker-composer
- 微服務
- protoBuf
- GRPC
- tls
- consul
- micro
- crontab
- shell調用
- gorhill/cronexpr
- raft
- go操作etcd
- mongodb