golang 棧、堆分配分析及CPU、內存性能情況


一、逃逸分析

堆:一般來講是人為手動進行管理,手動申請、分配、釋放。一般所涉及的內存大小並不定,一般會存放較大的對象。另外其分配相對慢,涉及到的指令動作也相對多

棧:由編譯器進行管理,自動申請、分配、釋放。一般不會太大,我們常見的函數參數(不同平台允許存放的數量不同),局部變量等等都會存放在棧上

反編譯為匯編代碼: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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM