一、逃逸分析
堆:一般來講是人為手動進行管理,手動申請、分配、釋放。一般所涉及的內存大小並不定,一般會存放較大的對象。另外其分配相對慢,涉及到的指令動作也相對多
棧:由編譯器進行管理,自動申請、分配、釋放。一般不會太大,我們常見的函數參數(不同平台允許存放的數量不同),局部變量等等都會存放在棧上
反編譯為匯編代碼:go tool compile -S main.go
棧、堆逃逸分析:go build -gcflags '-m -l' main.go
二、CPU、內存性能情況
1、time go run main.go
real 0m0.843s //從程序開始到結束,實際度過的時間;
user 0m0.216s //程序在用戶態度過的時間;
sys 0m0.389s //程序在內核態度過的時間
2、/usr/bin/time -v go run test2.go
3、調用 runtime
中的 ReadMemStats()
方法獲得內存信息,然后通過 log
打印出來。
package main import ( "log" "runtime" "time" ) func readMemStats() { var ms runtime.MemStats runtime.ReadMemStats(&ms) log.Printf(" ===> Alloc:%d(bytes) HeapIdle:%d(bytes) HeapReleased:%d(bytes)", ms.Alloc, ms.HeapIdle, ms.HeapReleased) } func test() { //slice 會動態擴容,用slice來做堆內存申請 container := make([]int, 8) log.Println(" ===> loop begin.") for i := 0; i < 32*1000*1000; i++ { container = append(container, i) if ( i == 16*1000*1000) { readMemStats() } } log.Println(" ===> loop end.") } func main() { log.Println(" ===> [Start].") readMemStats() test() readMemStats() log.Println(" ===> [force gc].") runtime.GC() //強制調用gc回收 log.Println(" ===> [Done].") readMemStats() go func() { for { readMemStats() time.Sleep(10 * time.Second) } }() time.Sleep(3600 * time.Second) //睡眠,保持程序不退出 }
4、pprof網頁監控
package main import ( "log" "runtime" "time" "net/http" _ "net/http/pprof" ) func readMemStats() { var ms runtime.MemStats runtime.ReadMemStats(&ms) log.Printf(" ===> Alloc:%d(bytes) HeapIdle:%d(bytes) HeapReleased:%d(bytes)", ms.Alloc, ms.HeapIdle, ms.HeapReleased) } func test() { //slice 會動態擴容,用slice來做堆內存申請 container := make([]int, 8) log.Println(" ===> loop begin.") for i := 0; i < 32*1000*1000; i++ { container = append(container, i) if ( i == 16*1000*1000) { readMemStats() } } log.Println(" ===> loop end.") } func main() { //啟動pprof go func() { log.Println(http.ListenAndServe("0.0.0.0:10000", nil)) }() log.Println(" ===> [Start].") readMemStats() test() readMemStats() log.Println(" ===> [force gc].") runtime.GC() //強制調用gc回收 log.Println(" ===> [Done].") readMemStats() go func() { for { readMemStats() time.Sleep(10 * time.Second) } }() time.Sleep(3600 * time.Second) //睡眠,保持程序不退出 }
記錄了目前的內存情況:http://127.0.0.1:10000/debug/pprof/heap?debug=1
記錄了目前的CPU情況:http://127.0.0.1:10000/debug/pprof/
5、gin使用pprof
5.1 安裝:go get https://github.com/gin-contrib/pprof
5.2 在main.go寫入監控:
package main import ( "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" ) func main() { s := gin.Default() // 方式一:性能 pprof.Register(s) // 方式二:性能 - 授權訪問 a := s.Group("/admin", gin.BasicAuth(gin.Accounts{"root": "888000"})) pprof.RouteRegister(a) s.Run(":8080") }
5.3 web訪問:http://127.0.01:8080/admin/debug/pprof/
5.4 頁面參數:
類型 | 描述 | 備注 |
---|---|---|
allocs | 內存分配情況的采樣信息 | 可以用瀏覽器打開, 但可讀性不高 |
blocks | 阻塞操作情況的采樣信息 | 可以用瀏覽器打開, 但可讀性不高 |
cmdline | 顯示程序啟動命令及參數 | 可以用瀏覽器打開 |
goroutine | 當前所有協程的堆棧信息 | 可以用瀏覽器打開, 但可讀性不高 |
heap | 堆上內存使用情況的采樣信息 | 可以用瀏覽器打開, 但可讀性不高 |
mutex | 鎖爭用情況的采樣信息 | 可以用瀏覽器打開, 但可讀性不高 |
profile | CPU 占用情況的采樣信息, 持續 30s | 瀏覽器打開會下載文件 |
threadcreate | 系統線程創建情況的采樣信息 | 可以用瀏覽器打開, 但可讀性不高 |
trace | 程序運行跟蹤信息 | 瀏覽器打開會下載文件 |
5.5 終端交互命令:
- go tool pprof http://localhost:8080/debug/pprof/profile?seconds=60
輸入 top10
項 | 說明 |
---|---|
flat | 給定函數上運行耗時 |
flat% | 同上的 CPU 運行耗時總比例 |
sum% | 給定函數累積使用 CPU 總比例 |
cum | 當前函數加上它之上的調用運行總耗時 |
cum% | 同上的 CPU 運行耗時總比例 |
-
go tool pprof http://localhost:8080/debug/pprof/heap
type 類型
項 | 說明 |
---|---|
inuse_space | 分析應用程序的常駐內存占用情況 |
alloc_objects | 分析應用程序的內存臨時分配情況 |
-
go tool pprof http://localhost:8080/debug/pprof/block
-
go tool pprof http://localhost:8080/debug/pprof/mutex
5.6 可視化界面
啟動方式一:go tool pprof -http=:8080 cpu.prof
啟動方式二:go tool pprof cpu.prof