中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang?pprof監控memory?block?mutex使用的方法是什么

發布時間:2023-04-08 16:53:09 來源:億速云 閱讀:136 作者:iii 欄目:開發技術

這篇文章主要介紹“golang pprof監控memory block mutex使用的方法是什么”,在日常操作中,相信很多人在golang pprof監控memory block mutex使用的方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”golang pprof監控memory block mutex使用的方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

profile

profile的中文被翻譯輪廓,對于計算機程序而言,拋開業務邏輯不談,它的輪廓是是啥呢?不就是cpu,內存,各種阻塞開銷,線程,協程概況 這些運行指標或環境。golang語言自帶了工具庫來幫助我們描述,探測,分析這些指標或者環境信息,讓我們來學習它。

還記得之前用go trace 生成的網頁圖嗎?

golang?pprof監控memory?block?mutex使用的方法是什么

trace 網頁顯示

里面是不是也有 3個名字帶有blocking的 profile的輪廓圖,分別是Network blocking profile,Synchronization blocking profile,Syscall blocking profile ,而它與今天要說的block 統計有沒有什么關聯?先說下結論,block統計的內容有重合,但是不多,并且統計數據來源是不同的

Synchronization blocking profile 和 今天的block統計 內容 是一致的,都是blobk信息,不過統計方式不同。

然后之所以 memory,block,mutex 把這3類數據放在一起講,是因為他們統計的原理是很類似的,好的,在了解統計原理之前,先簡單看下如何使用golang提供的工具對這些數據類型進行分析。

如何使用

在看使用代碼前,還需要了解清楚對這3種類型的指標對哪些數據進行統計。

兩種方式都比較常見,首先來看下http 接口暴露這些性能指標的方式。

http 接口暴露的方式

package main
import (
 "log"
  "net/http"
 _ "net/http/pprof"
)
func main() {
  log.Println(http.ListenAndServe(":6060", nil))
}

使用方式相當容易,直接代碼引入net/http/pprof ,便在默認的http處理器上注冊上了相關路由,引入包的目的就是為了調用對應包的init方法注冊路由。下面就是引用包的init方法。

// src/net/http/pprof/pprof.go:80
func init() {
 http.HandleFunc("/debug/pprof/", Index)
 http.HandleFunc("/debug/pprof/cmdline", Cmdline)
 http.HandleFunc("/debug/pprof/profile", Profile)
 http.HandleFunc("/debug/pprof/symbol", Symbol)
 http.HandleFunc("/debug/pprof/trace", Trace)
}

接下來訪問路由 http://127.0.0.1:6060/debug/pprof/  便能看到下面網頁內容了。

golang?pprof監控memory?block?mutex使用的方法是什么

標注為紅色的部分就是今天要講的內容,點擊它們的鏈接會跳到對應的網頁看到統計信息。我們挨個來看下。

allocs ,heap

這兩個值都是記錄程序內存分配的情況。

heap profile: 7: 5536 [110: 2178080] @ heap/1048576
2: 2304 [2: 2304] @ 0x100d7e0ec 0x100d7ea78 0x100d7f260 0x100d7f78c 0x100d811cc 0x100d817d4 0x100d7d6dc 0x100d7d5e4 0x100daba20
# 0x100d7e0eb runtime.allocm+0x8b  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:1881
# 0x100d7ea77 runtime.newm+0x37  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:2207
# 0x100d7f25f runtime.startm+0x11f  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:2491
# 0x100d7f78b runtime.wakep+0xab  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:2590
# 0x100d811cb runtime.resetspinning+0x7b /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:3222
# 0x100d817d3 runtime.schedule+0x2d3  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:3383
# 0x100d7d6db runtime.mstart1+0xcb  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:1419
# 0x100d7d5e3 runtime.mstart0+0x73  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:1367
# 0x100daba1f runtime.mstart+0xf  /Users/lanpangzi/goproject/src/go/src/runtime/asm_arm64.s:117

在 go1.17.12 這兩者的信息輸出其實是一樣的,實現的代碼也基本一致,僅僅是在名稱上做了區分

golang?pprof監控memory?block?mutex使用的方法是什么

按pprof http服務器啟動網頁上的顯示來說,allocs 是過去內存的采樣,heap 是存活對象的采用記錄,然而實際上在代碼實現上兩者是一致的。并沒有做區分。

下面來講下網頁輸出內容的含義

heap profile: 7: 5536 [110: 2178080] @ heap/1048576

輸出的第一行含義分別是: 7 代表 當前活躍的對象個數 5536 代表 當前活躍對象占用的字節數 110 代表 所有(包含歷史的對象)對象個數 2178080 代表 所有對象(包含歷史的對象)占用的對象字節數 1048576  控制了內存采樣的頻率,1048576 是兩倍的內存采樣頻率的大小,默認采樣頻率是512kb 即平均每512kb就會采樣一次,注意這個值512kb不是絕對的達到512kb就會進行采樣,而是從一段時間內的采樣來看的一個平均值。

接下來就是函數調用堆棧信息,來看第一行

2: 2304 [2: 2304] @ 0x100d7e0ec 0x100d7ea78 0x100d7f260 0x100d7f78c 0x100d811cc 0x100d817d4 0x100d7d6dc 0x100d7d5e4 0x100daba20

從左往右看: 2 代表 在該函數棧上當前活躍的對象個數 2304 代表 在該函數棧上當前活躍的對象所占用的字節數 方括號內的2   代表 在該函數棧上所有(包含歷史的對象)對象個數 方括號內的2304 代表 在該函數棧上所有(包含歷史的對象)對象所占用的字節數

然后是棧上pc寄存器的值。再往后就是具體的棧函數名信息了。

block

接下來看看block會對哪些行為產生記錄,每次程序鎖阻塞發生時,select 阻塞,channel通道阻塞,wait group 產生阻塞時就會記錄一次阻塞行為。對阻塞行為的記錄其實是和trace 的Synchronization blocking profile 是一致的,但是和其他兩個blocking profile 不一樣。

要得到block的輸出信息首先要開啟下記錄block的開關.

   // 1 代表 全部采樣,0 代表不進行采用, 大于1則是設置納秒的采樣率
 runtime.SetBlockProfileRate(1)

這個采樣率是怎樣計算的,我們來看下具體代碼。

// src/runtime/mprof.go:409
func blocksampled(cycles, rate int64) bool {
 if rate <= 0 || (rate > cycles && int64(fastrand())%rate > cycles) {
  return false
 }
 return true
}

cycles你可以把它理解成也是一個納秒級的事件,rate就是我們設置的納秒時間,如果 cycles大于等于rate則直接記錄block行為,如果cycles小于rate的話,則需要fastrand函數乘以設置的納秒時間rate 來決定是否采樣了。

然后回過頭來看看網頁的輸出信息

--- contention:
cycles/second=1000000000
180001216583 1 @ 0x1002a1198 0x1005159b8 0x100299fc4
# 0x1002a1197 sync.(*Mutex).Lock+0xa7 /Users/lanpangzi/goproject/src/go/src/sync/mutex.go:81
# 0x1005159b7 main.main.func2+0x27 /Users/lanpangzi/goproject/src/go/main/main.go:33

contention 是為這個profile文本信息取的名字,總之中文翻譯是爭用。

cycles/second 是每秒鐘的周期數,用它來表示時間也是為了更精確,其實你可以發現在我的機器上每秒是10的9次方個周期,換算成納秒就是1ns一個周期時間了。

接著的180001216583 是阻塞的周期數,其實周期就是cputicks,那么180001216583除以 cycles/second 1000000000得到的就是阻塞的秒數了。

接著 1代表阻塞的次數。

無論是阻塞周期時長還是次數,都是一個累加值,即在相同的地方阻塞會導致這個值變大,并且次數會增加。剩下的部分就是函數堆棧信息了。

mutex

接著來看mutex相關內容,block也在鎖阻塞時記錄阻塞行為,那么mutex與它有什么不同?

直接說下結論,mutex是在解鎖unlock時才會記錄一次阻塞行為,而block在記錄mutex鎖阻塞信息時,是在開始執行lock調用的時候記錄的。

要想記錄mutex信息,和block類似,也需要開啟mutex采樣開關。

   // 0 代表不進行采用, 1則全部采用,大于1則是一個隨機采用
    runtime.SetMutexProfileFraction(1)

來看看采樣的細節代碼,代碼版本go1.17.12

if rate > 0 && int64(fastrand())%rate == 0 {
  saveblockevent(cycles, rate, skip+1, mutexProfile)
 }

可以看到fastrand() 與rate取模等于0才會去采樣,rate如果設置成1,則任何數與整數與1取模都會得到0,所以設置為1為完全采用,大于1比如rate設置為2,則要求fastrand必須是2的倍數才能被采樣。

接著來看下網頁的輸出信息。

--- mutex:
cycles/second=1000000812
sampling period=1
180001727833 1 @ 0x100b9175c 0x100e05840 0x100b567ec 0x100b89fc4
# 0x100b9175b sync.(*Mutex).Unlock+0x8b /Users/lanpangzi/goproject/src/go/src/sync/mutex.go:190
# 0x100e0583f main.main+0x19f   /Users/lanpangzi/goproject/src/go/main/main.go:39
# 0x100b567eb runtime.main+0x25b  /Users/lanpangzi/goproject/src/go/src/runtime/proc.go:255

第一行mutex就是profile文本信息的名稱了,同樣也和block一樣,采用cpu周期數計時,但是多了一個sampling period ,這個就是我們設置的采用頻率。

接下來的數據都和block類似,180001727833就是鎖阻塞的周期, 1為解鎖的次數。然后是解鎖的堆棧信息。

介紹完利用http服務查看pprof性能指標的方式來看看,如何用代碼來生成這些pprof的二進制或者文本文件。

代碼生成profile文件的方式

首先來看看如何對內存信息生成pprof文件。

os.Remove("heap.out")
 f, _ := os.Create("heap.out")
 defer f.Close()

 err := pprof.Lookup("heap").WriteTo(f, 1)
 if err != nil {
  log.Fatal(err)
 }

lookup 傳遞的heap參數也可以改成allocs,不過輸出的內容是一致的。

WriteTo 第二個參數叫做debug,傳1代表 會生成可讀的文本文件,就和http服務看heap allocs的網頁一樣的。傳0代表是要生成一個二進制文件。生成的二進制文件可以用go tool pprof pprof文件名 去分析,關于go tool pprof 工具的使用網上有相當多的資料,這里就不再展開了。

然后來看看如何生成block的pprof文件。

runtime.SetBlockProfileRate(1)
 os.Remove("block.out")
 f, _ := os.Create("block.out")
 defer f.Close()

 err := pprof.Lookup("block").WriteTo(f, 1)
 if err != nil {
  log.Fatal(err)
 }

pprof.Lookup方法傳遞block即可生成文件了,使用方式和生成內存分析文件一致,,傳1代表 會生成可讀的文本文件,就和http服務看block的網頁一樣的。傳0代表是要生成一個二進制文件。生成的二進制文件可以用go tool pprof pprof文件名 去分析。

最后看看mutex,和前面兩者基本一致僅僅是Lookup傳遞的參數有變化,這里就不再敘述了。

 runtime.SetMutexProfileFraction(1)
 os.Remove("mutex.out")
 f, _ := os.Create("mutex.out")
 defer f.Close()

 err := pprof.Lookup("mutex").WriteTo(f, 1)
 if err != nil {
  log.Fatal(err)
 }

到此,關于“golang pprof監控memory block mutex使用的方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永城市| 张家界市| 鞍山市| 肇州县| 库车县| 旬阳县| 榆中县| 渭源县| 庆元县| 永顺县| 天峻县| 建阳市| 荣昌县| 长武县| 桐乡市| 临沂市| 金塔县| 波密县| 潼关县| 吴旗县| 景洪市| 台江县| 马公市| 荔波县| 宁津县| 襄城县| 泗水县| 赣榆县| 台湾省| 开远市| 会昌县| 康保县| 扶沟县| 民和| 永寿县| 古浪县| 连江县| 乌海市| 大足县| 循化| 兴山县|