哈爾濱做網(wǎng)站哪好網(wǎng)站頁面關(guān)鍵詞優(yōu)化
起因
被同事靈魂拷問:圖中這塊空白是什么東西?
豆包回答說是數(shù)據(jù)采樣不完整,特定函數(shù)或代碼段未被調(diào)用之類的原因,感覺都不太合理。
之前看過一篇文章說:Heap Profiling的采樣是無時無刻不在發(fā)生的,執(zhí)行一次profiling僅僅是dump一下迄今為止的數(shù)據(jù)快照。這篇文章更加推翻了前面"數(shù)據(jù)采樣不完整"的假設(shè)。那火焰圖中的空白到底是啥,我們親自試一下。
實驗
參考:使用火焰圖對 Go 程序進(jìn)行性能分析
實驗設(shè)計
在一個函數(shù)中調(diào)用另外的函數(shù),在多種位置申請內(nèi)存,查看火焰圖的空白情況。
前置準(zhǔn)備
- 安裝環(huán)境
- 編寫測試代碼
- 在Goland中運行測試代碼,可以通過 pprof 的 HTTP 接口訪問
http://localhost:8000/debug/pprof/heap?debug=1
- 在終端中執(zhí)行以下命令,在頁面中展示火焰圖。其中,
-http=":8081"
表示用于查看火焰圖的端口,http://localhost:8000/debug/pprof/heap
表示采集的數(shù)據(jù)源。需要注意,每次運行此命令時,生成的是當(dāng)前堆快照,如果代碼有變更,或者想要獲取最新結(jié)果,需要中斷后重新運行此命令。
go tool pprof -http=":8081" http://localhost:8000/debug/pprof/heap
- 火焰圖分析方法:選擇VIEW - Flame Graph (old)后,再選擇SAMPLE - alloc_space。我們主要看這個,其它的選項也可以參考。
函數(shù)調(diào)用關(guān)系
func allocate1() {allocate2()allocate3()
}
代碼1:allocate1本身占用空間
package mainimport ("net/http"_ "net/http/pprof""time"
)func allocate1() {var s []stringfor i := 0; i < 10000; i++ {// allocate1占用的空間for i := 0; i < 10; i++ {s = append(s, "This is a sample string")}// allocate2占用的空間allocate2()// allocate3占用的空間allocate3()}
}func allocate2() {var s []stringfor i := 0; i < 10; i++ {s = append(s, "This is a sample string")}
}
func allocate3() {var s []stringfor i := 0; i < 10; i++ {s = append(s, "This is a sample string")}
}func main() {go func() {for {allocate1()time.Sleep(1 * time.Second)}}()http.ListenAndServe(":8000", nil)
}
生成的火焰圖:
代碼2:allocate本身不占空間
把13-15行注釋掉,讓allocate1不占空間
package mainimport ("net/http"_ "net/http/pprof""time"
)func allocate1() {//var s []stringfor i := 0; i < 10000; i++ {// allocate1占用的空間//for i := 0; i < 10; i++ {// s = append(s, "This is a sample string")//}// allocate2占用的空間allocate2()// allocate3占用的空間allocate3()}
}func allocate2() {var s []stringfor i := 0; i < 10; i++ {s = append(s, "This is a sample string")}
}
func allocate3() {var s []stringfor i := 0; i < 10; i++ {s = append(s, "This is a sample string")}
}func main() {go func() {for {allocate1()time.Sleep(1 * time.Second)}}()http.ListenAndServe(":8000", nil)
}
生成的火焰圖:
結(jié)論
當(dāng)allocate1本身占用空間的時候,火焰圖中的空白存在。當(dāng)allocate1本身不占用空間的時候,火焰圖被填滿,不存在空白。說明空白的部分是上一級函數(shù)內(nèi)部對象占用的空間。