精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

萬(wàn)字長(zhǎng)文講解 Golang pprof 的使用

開(kāi)發(fā) 前端
cpu在http接口暴露的分析界面中有個(gè)profile的鏈接,點(diǎn)擊后,應(yīng)用程序會(huì)采集30s的cpu運(yùn)行信息后然后生成一個(gè)二進(jìn)制文件,所以本質(zhì)上對(duì)cpu的分析都是通過(guò)一個(gè)二進(jìn)制文件進(jìn)行的。

大家好,我是藍(lán)胖子,說(shuō)到golang的性能分析,不得不提的就是其自身?yè)碛械膒prof,它提供了從cpu,內(nèi)存,阻塞情況,協(xié)程,線(xiàn)程,乃至程序運(yùn)行軌跡trace的分析,可以說(shuō)相當(dāng)強(qiáng)大了。

今天我將會(huì)用較長(zhǎng)的篇幅闡述 應(yīng)該如何使用pprof工具來(lái) 對(duì)cpu,內(nèi)存,阻塞情況,協(xié)程,線(xiàn)程 這幾個(gè)維度去進(jìn)行分析。

其實(shí)總結(jié)出來(lái)Golang pprof的使用方式,可以用下面的思維導(dǎo)圖來(lái)表示。

圖片圖片

要么在程序中通過(guò)http接口的方式暴露相應(yīng)的pprof的采集控制界面,要么就是在程序中通過(guò)代碼開(kāi)啟對(duì)應(yīng)指標(biāo)的采集樣本功能,采集一段時(shí)間的樣本后生成二進(jìn)制文件,最后通過(guò) go tool pprof 命令去對(duì)樣本的數(shù)據(jù)進(jìn)行分析。

分析的方式也有兩種,

  • 通過(guò)命令行開(kāi)啟一個(gè)交互終端
  • 通過(guò)瀏覽器將二進(jìn)制文件的信息展示出來(lái)

我們可以通過(guò)下述的代碼通過(guò)http接口的方式暴露相應(yīng)的pprof的采集控制界面。

import (  
    "log"  
    "net/http"    
    "net/http/pprof"    
    "time")  
  
func main() {  
    mux := http.NewServeMux()  
    mux.HandleFunc("/debug/pprof/", pprof.Index)  
    mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)  
    mux.HandleFunc("/debug/pprof/profile", pprof.Profile)  
    mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)  
    mux.HandleFunc("/debug/pprof/trace", pprof.Trace)  
    go func() { log.Fatal(http.ListenAndServe(":8080", mux)) }()  
    time.Sleep(time.Hour)  
}

接著訪(fǎng)問(wèn)下http://localhost:8080/debug/pprof/ 便會(huì)出現(xiàn)各種維度指標(biāo),可以點(diǎn)擊進(jìn)去查看具體的指標(biāo)信息。如下所示:

圖片圖片

接下來(lái)我們來(lái)分析下各個(gè)指標(biāo)在 http接口或者生成的二進(jìn)制文件  輸出的各種信息究竟代表什么含義。

在下面的分析中我會(huì)分別的從http接口暴露指標(biāo)的方式和二進(jìn)制文件的方式分別介紹如何看懂各種指標(biāo)的輸出信息。

cpu

cpu在http接口暴露的分析界面中有個(gè)profile的鏈接,點(diǎn)擊后,應(yīng)用程序會(huì)采集30s的cpu運(yùn)行信息后然后生成一個(gè)二進(jìn)制文件,所以本質(zhì)上對(duì)cpu的分析都是通過(guò)一個(gè)二進(jìn)制文件進(jìn)行的。

除了上述提到http接口暴露出cpu指標(biāo)外,我們還可以通過(guò)下面的代碼,在程序中顯示的開(kāi)啟cpu指標(biāo)的采集。在這個(gè)例子中,我通過(guò)busyCpu 方法不斷的進(jìn)行加法運(yùn)算來(lái)模擬頻繁的cpu操作。

import (  
    "github.com/pkg/profile"  
    "log"  
    "os"    
    "os/signal"    
    "syscall")  
func main() {  
    p := profile.Start(profile.CPUProfile,  
       profile.ProfilePath("profile"),  
       profile.NoShutdownHook,  
    )  
    defer p.Stop()  
    go busyCpu()  
    c := make(chan os.Signal, 1)  
    signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)  
    defer signal.Stop(c)  
    <-c  
}  
  
func busyCpu() {  
    i := uint(1000000)  
    for {  
       log.Println("sum number", i, Add(i, i+1))  
       i++  
    }  
}  
  
func Add(a, b uint) uint {  
    return a + b  
}

啟動(dòng)終端分析

在得到二進(jìn)制文件后,我們可以使用如下命令來(lái)啟動(dòng)一個(gè)交互終端來(lái)分析cpu的使用情況。

go tool  pprof cpuprofile/cpu.pprof

輸入top命令得到如下結(jié)果:

(base) ?  cpu go tool  pprof cpuprofile/cpu.pprof
Type: cpu
Time: Mar 4, 2024 at 3:14pm (CST)
Duration: 4.35s, Total samples = 200ms ( 4.60%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 200ms, 100% of 200ms total
Showing top 10 nodes out of 16
      flat  flat%   sum%        cum   cum%
     190ms 95.00% 95.00%      190ms 95.00%  syscall.syscall
      10ms  5.00%   100%       10ms  5.00%  runtime.pthread_cond_signal
         0     0%   100%      190ms 95.00%  internal/poll.(*FD).Write
         0     0%   100%      190ms 95.00%  internal/poll.ignoringEINTRIO (inline)
         0     0%   100%      190ms 95.00%  log.(*Logger).output
         0     0%   100%      190ms 95.00%  log.Println (inline)
         0     0%   100%      190ms 95.00%  main.busyCpu
         0     0%   100%      190ms 95.00%  os.(*File).Write
         0     0%   100%      190ms 95.00%  os.(*File).write (inline)
         0     0%   100%       10ms  5.00%  runtime.exitsyscallfast.func1

每個(gè)列的含義如下:

flat:函數(shù)自身的運(yùn)行耗時(shí)(排除了子函數(shù)的調(diào)用耗時(shí))

flat%:flat運(yùn)行耗時(shí)占用總的采集樣本的時(shí)間和的比例,這里所有節(jié)點(diǎn)運(yùn)行的flat時(shí)間和為200ms。

sum%:命令行返回結(jié)果中函數(shù)自身和其之上的函數(shù)運(yùn)行的flat時(shí)間占所有采集樣本時(shí)間總和的比例。

cum:當(dāng)前函數(shù)和其子函數(shù)的調(diào)用耗時(shí)總的運(yùn)行時(shí)間

cum%:cum耗時(shí)占總的采集樣本的時(shí)間和的比例。

分析中可以看出主要是打印日志占用了比較大的cpu。

在命令行中可以輸入svg,來(lái)輸出cpu性能剖析的profile 圖。

(pprof) svg 
Generating report in profile001.svg

圖片圖片

圖中顯示了函數(shù)的調(diào)用關(guān)系,函數(shù)框中顯示了函數(shù)自身的運(yùn)行時(shí)長(zhǎng)flat和其自身及其子函數(shù)運(yùn)行時(shí)長(zhǎng)cum,箭頭上的時(shí)間則是其子函數(shù)的cum運(yùn)行時(shí)長(zhǎng),時(shí)間越大,箭頭越粗。

將二進(jìn)制文件信息輸出到瀏覽器上

可以通過(guò)如下命令來(lái)啟動(dòng)瀏覽器查看cpu使用情況,

go tool pprof -http=:8082  cpuprofile/cpu.pprof
火焰圖分析性能問(wèn)題

通過(guò)web界面,我們除了按剛才的top和調(diào)用耗時(shí)圖像外,甚至還能通過(guò)火焰圖的方式,來(lái)查看cpu調(diào)用耗時(shí),火焰圖上,函數(shù)的調(diào)用順序是從上往下,函數(shù)占用cpu越長(zhǎng),那么在火焰圖上的區(qū)塊就會(huì)越大。 火焰圖中顯示的是cum值。

圖片圖片

peek

圖片圖片

除了像top那樣輸出函數(shù)的耗時(shí)情況,還會(huì)輸出調(diào)用函數(shù)和被調(diào)用函數(shù),調(diào)用順序從上到下。

source

Pasted image 20240304175712.png

在web界面可以通過(guò)source視圖去查看函數(shù)節(jié)點(diǎn)的耗時(shí)以及它的子調(diào)用函數(shù)中耗時(shí)的地方,第一欄時(shí)間是flat耗時(shí),第二欄時(shí)間是cum耗時(shí)。 耗時(shí)百分比是cum耗時(shí)占樣本總和的百分比。

內(nèi)存

http接口暴露的控制臺(tái)查看

通過(guò)點(diǎn)擊heap或者allocs 鏈接可以查看內(nèi)存的分配情況,它們的輸出都是一致的。

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

下面來(lái)講下網(wǎng)頁(yè)輸出內(nèi)容的含義:

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

輸出的第一行含義分別是:

7 代表 當(dāng)前活躍的對(duì)象個(gè)數(shù)

5536 代表 當(dāng)前活躍對(duì)象占用的字節(jié)數(shù)

110 代表 所有(包含歷史的對(duì)象)對(duì)象個(gè)數(shù)

2178080 代表 所有對(duì)象(包含歷史的對(duì)象)占用的對(duì)象字節(jié)數(shù)

1048576 控制了內(nèi)存采樣的頻率,1048576 是兩倍的內(nèi)存采樣頻率的大小,默認(rèn)采樣頻率是512kb 即平均每512kb就會(huì)采樣一次,注意這個(gè)值512kb不是絕對(duì)的達(dá)到512kb就會(huì)進(jìn)行采樣,而是從一段時(shí)間內(nèi)的采樣來(lái)看的一個(gè)平均值。

接下來(lái)就是函數(shù)調(diào)用堆棧信息,來(lái)看第一行。

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

從左往右看:

2 代表 在該函數(shù)棧上當(dāng)前活躍的對(duì)象個(gè)數(shù)

2304 代表 在該函數(shù)棧上當(dāng)前活躍的對(duì)象所占用的字節(jié)數(shù)

方括號(hào)內(nèi)的2 代表 在該函數(shù)棧上所有(包含歷史的對(duì)象)對(duì)象個(gè)數(shù)

方括號(hào)內(nèi)的2304 代表 在該函數(shù)棧上所有(包含歷史的對(duì)象)對(duì)象所占用的字節(jié)數(shù)

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

通過(guò)二進(jìn)制文件查看

我們可以使用如下代碼生成一個(gè)關(guān)于內(nèi)存使用情況的二進(jìn)制profile文件,下述代碼中我用 allocMem 函數(shù)不斷對(duì)一個(gè)字節(jié)數(shù)組進(jìn)行append操作來(lái)模擬內(nèi)存不斷增大的情況。

package main  
  
import (  
    "github.com/pkg/profile"  
    "log"   
     "os"    
     "os/signal"    
     "syscall"    
     "time")  
  
func main() {  
    p := profile.Start(profile.MemProfile,  
       profile.ProfilePath("profile"),  
       profile.NoShutdownHook,  
    )  
    defer p.Stop()  
    go allocMem()  
    c := make(chan os.Signal, 1)  
    signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)  
    defer signal.Stop(c)  
    <-c  
  
}  
  
func allocMem() {  
    buf := []byte{}  
    mb := 1024 * 1024  
  
    for {  
       buf = append(buf, make([]byte, mb)...)  
       log.Println("total allocated memory", len(buf))  
       time.Sleep(time.Second)  
    }  
}

生成的二進(jìn)制文件,和cpu分析一致,可以通過(guò)啟動(dòng)交互終端或者web瀏覽器去進(jìn)行查看,所以啟動(dòng)終端的方式我這里就暫時(shí)略去了, 講講不同點(diǎn), 針對(duì)于內(nèi)存,pprof在web 瀏覽器界面提供了幾個(gè)維度去分析。

inuse_space: 正在使用,尚未釋放的空間

inuse_object: 正在使用,尚未釋放的對(duì)象

alloc_space: 所有分配的空間,包含已釋放的

alloc_objects: 所有分配的對(duì)象,包含已釋放的

拿inuse_object舉例,性能剖析圖是這樣的,箭頭顯示了正在使用的對(duì)象個(gè)數(shù),其中 main.allocMem函數(shù)自身有一個(gè)4MB多的對(duì)象,其子函數(shù)有4個(gè)對(duì)象。

圖片圖片

我們可以根據(jù)source 選項(xiàng)也能得到同樣的分析結(jié)果。

圖片圖片

block

block可用于分析程序鎖mutex,select ,channel通道,  wait group 的阻塞行為。

但是block通常是關(guān)閉的,需要通過(guò)下面代碼進(jìn)行開(kāi)啟。

runtime.SetBlockProfileRate(1)

其中,SetBlockProfileRate 的參數(shù)名為rate,rate不同,對(duì)block事件的采樣頻率不同。

  • 1  代表 始終對(duì)阻塞事件進(jìn)行采樣
  • <= 0 代表關(guān)閉阻塞事件的采樣
  • 除了上述兩種情況,SetBlockProfileRate 的參數(shù)傳遞的將會(huì)是一個(gè)納秒值。

如果阻塞的時(shí)間大于了rate值則直接進(jìn)行采樣,如果阻塞的時(shí)間小于rate,那么阻塞事件將會(huì)有(阻塞時(shí)間)/rate 的可能性被采集到。

??????  注意下block事件的記錄時(shí)機(jī)為獲取鎖資源或者channel 資源時(shí),進(jìn)行記錄,也就是發(fā)生在lock函數(shù)中。

http接口暴露的控制臺(tái)查看

通過(guò)點(diǎn)擊http接口暴露的pprof控制的block鏈接,可以查看程序中block的情況,瀏覽器輸出如下:

--- contention:
cycles/secnotallow=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 是為這個(gè)profile文本信息取的名字,總之中文翻譯是爭(zhēng)用。

cycles/second 是cpu時(shí)鐘每秒鐘的周期數(shù),用它來(lái)表示時(shí)間也是為了更精確,其實(shí)你可以發(fā)現(xiàn)在我的機(jī)器上每秒是10的9次方個(gè)周期,換算成納秒就是1ns一個(gè)周期時(shí)間了。

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

接著 1 代表阻塞的次數(shù)。

無(wú)論是阻塞周期時(shí)長(zhǎng)還是次數(shù),都是一個(gè)累加值,即在相同的地方阻塞會(huì)導(dǎo)致這個(gè)值變大,并且次數(shù)會(huì)增加。剩下的部分就是函數(shù)堆棧信息了。

使用二進(jìn)制文件查看

可以通過(guò)如下代碼生成block的二進(jìn)制文件,通過(guò)在主協(xié)程中使用lock方法后,不釋放鎖資源,啟動(dòng)子協(xié)程,讓子協(xié)程同樣使用lock方法模擬系統(tǒng)阻塞的情況。

import (  
    "fmt"  
    "github.com/pkg/profile"   
    "runtime"    
    "sync"    
    "time")  
  
/*  
*  
每次程序鎖阻塞發(fā)生時(shí),select 阻塞,channel通道阻塞,  
wait group 產(chǎn)生阻塞時(shí)就會(huì)記錄一次阻塞行為  
*/  
func main() {  
  
    runtime.SetBlockProfileRate(1)  
    p := profile.Start(profile.BlockProfile,  
       profile.ProfilePath("profile"),  
       profile.NoShutdownHook)  
    defer p.Stop()  
    mLock := sync.Mutex{}  
    mLock.Lock()  
    go mockBlock(&mLock)  
    go mockBlock(&mLock)  
    time.Sleep(time.Second * 2)  
    mLock.Unlock()  
    time.Sleep(time.Second)  
    fmt.Println("End")  
}  
  
func mockBlock(l *sync.Mutex) {  
    l.Lock()  
    defer l.Unlock()  
    fmt.Println("獲取鎖")  
}

生成的profile文件,同樣可以通過(guò)命令行和web瀏覽器的方式進(jìn)行查看。

這里我直接采樣瀏覽器的方式瀏覽。

go tool pprof -http=:8083  ./profile/block.pprof

block提供了兩個(gè)維度去觀察阻塞事件  ,contention 發(fā)生阻塞的事件個(gè)數(shù),delay  發(fā)生阻塞的時(shí)間。

contention 生成的profile圖如下,可以看到發(fā)生阻塞的函數(shù)是main.mockBlock ,其自身包括其調(diào)用子函數(shù)的阻塞次數(shù)是2次。

圖片圖片

delay生成的profile 圖如下所示,main.mockBlock其自身包括其調(diào)用子函數(shù)的阻塞時(shí)間是4s。

圖片圖片

?????? 無(wú)論是阻塞次數(shù)還是阻塞時(shí)間,如果同一個(gè)函數(shù)發(fā)生了阻塞,那么次數(shù)和阻塞時(shí)間都會(huì)累加上去。

使用 阻塞時(shí)間/阻塞次數(shù) 能得到平均每次阻塞多長(zhǎng)時(shí)間。

mutex

mutex 記錄的是持有鎖的時(shí)間,注意下它和block的區(qū)別,block記錄的是在獲取鎖之前阻塞的時(shí)間。并且block還可以記錄channel。

mutex 的采集默認(rèn)情況下也是關(guān)閉的,需要用以下代碼進(jìn)行開(kāi)啟。

runtime.SetMutexProfileFraction(1)

其中,SetMutexProfileFraction 的參數(shù)名為rate,rate不同,對(duì)block事件的采樣頻率不同。

  • 1  代表 始終對(duì)持有鎖事件進(jìn)行采樣
  • = 0 代表關(guān)閉阻塞事件的采樣
  • < 0 將會(huì)把當(dāng)前的rate值讀取出來(lái)
  • > 1 將會(huì)有1/rate 的持有鎖事件被采集

http接口暴露的控制臺(tái)查看

通過(guò)點(diǎn)擊http接口暴露的pprof控制的mutex鏈接,可以查看程序中鎖持有的的情況,瀏覽器輸出如下:

--- mutex:
cycles/secnotallow=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文本信息的名稱(chēng)了,同樣也和block一樣,采用cpu周期數(shù)計(jì)時(shí),但是多了一個(gè)sampling period ,這個(gè)就是我們?cè)O(shè)置的采用頻率。

接下來(lái)的數(shù)據(jù)都和block類(lèi)似,180001727833就是鎖持有的周期, 1為解鎖的次數(shù)。然后是解鎖的堆棧信息。

使用二進(jìn)制文件查看

我們可以通過(guò)如下代碼生成mutex的二進(jìn)制文件,模擬阻塞的情況和block一致,代碼不同的點(diǎn)是將樣本采集的對(duì)象從block替換成了mutex。

package main  
  
import (  
    "fmt"  
    "github.com/pkg/profile"    
    "runtime"    
    "sync"    
    "time")  
  
func main() {  
  
    runtime.SetMutexProfileFraction(1)  
    p := profile.Start(profile.MutexProfile,  
       profile.ProfilePath("profile"),  
       profile.NoShutdownHook)  
    defer p.Stop()  
    mLock := sync.Mutex{}  
    mLock.Lock()  
    go mockBlock(&mLock)  
    go mockBlock(&mLock)  
    time.Sleep(time.Second * 2)  
    mLock.Unlock()  
    time.Sleep(time.Second)  
    fmt.Println("End")  
}  
  
func mockBlock(l *sync.Mutex) {  
    l.Lock()  
    defer l.Unlock()  
    fmt.Println("獲取鎖")  
}

這里我同樣采用web瀏覽器的方式去查看mutext的剖析grapgh,mutex提供了兩個(gè)維度去觀察阻塞事件  ,contention 發(fā)生持有鎖的事件個(gè)數(shù),delay  持有鎖的時(shí)間。

以下是contention 維度的圖,可以看到在main方法中進(jìn)行中持有了一次鎖,在mockBlock方法中也持有了一次鎖。

圖片圖片

通過(guò)delay 維度可以發(fā)現(xiàn)main方法以及其子調(diào)用函數(shù),持有鎖的時(shí)間一共是2s。

圖片圖片

goroutine

http接口暴露的控制臺(tái)查看

點(diǎn)擊控制界面的goroutine鏈接,我們會(huì)看到在程序中g(shù)oroutine正在執(zhí)行的函數(shù)堆棧信息,界面如下:

圖片圖片

首先地址欄 /debug/pprof/goroutine?debug= 1 代表這是在訪(fǎng)問(wèn)goroutine指標(biāo)信息,debug =1 代表訪(fǎng)問(wèn)的內(nèi)容將會(huì)以文本可讀的形式展現(xiàn)出來(lái)。 debug=0 則是會(huì)下載一個(gè)goroutine指標(biāo)信息的二進(jìn)制文件。 debug = 2 將會(huì)把當(dāng)前所有協(xié)程的堆棧信息以文本可讀形式展示在網(wǎng)頁(yè)上。如下圖所示:

圖片圖片

debug =2 時(shí)的 如上圖所示,41代表協(xié)程的id,方括號(hào)內(nèi)running代表了協(xié)程的狀態(tài)是運(yùn)行中,接著就是該協(xié)程此時(shí)的堆棧信息了。

讓我們?cè)倩氐絛ebug = 1的分析上面去,剛才分析完了地址欄里的debug參數(shù),接著,我們看輸出的第一行。

goroutine profile: total 6 1 @ 0x102ad6c60 0x102acf7f4 0x102b04de0 0x102b6e850 0x102b6e8dc 0x102b6f79c 0x102c27d04 0x102c377c8 0x102d0fc74 0x102bea72c 0x102bebec0 0x102bebf4c 0x102ca4af0 0x102ca49dc 0x102d0b084 0x102d10f30 0x102d176a4 0x102b09fc4 # 0x102b04ddf internal/poll.runtime_pollWait+0x5f  /Users/xiongchuanhong/goproject/src/go/src/runtime/netpoll.go:303 # 0x102b6e84f internal/poll.(*pollDesc).wait+0x8f  /Users/xiongchuanhong/goproject/src/go/src/internal/poll/fd_poll_runtime.go:84 ......

goroutine profile 表明了這個(gè)profile的類(lèi)型。

total 6 代表此時(shí)一共有6個(gè)協(xié)程。

接著是下面一行,1 代表了在這個(gè)堆棧上,只有一個(gè)協(xié)程在執(zhí)行。但其實(shí)在計(jì)算出數(shù)字1時(shí),并不僅僅按堆棧去做區(qū)分,還依據(jù)了協(xié)程labels值,也就是 協(xié)程的堆棧和lebels標(biāo)簽值 共同構(gòu)成了一個(gè)key,而數(shù)字1就是在遍歷所有協(xié)程信息時(shí),對(duì)相同key進(jìn)行累加計(jì)數(shù)得來(lái)的。

我們可以通過(guò)下面的方式為協(xié)程設(shè)置labels。

pprof.SetGoroutineLabels(pprof.WithLabels(context.Background(), pprof.Labels("name", "lanpangzi", "age", "18")))

通過(guò)上述代碼,我可以為當(dāng)前協(xié)程設(shè)置了兩個(gè)標(biāo)簽值,分別是name和age,設(shè)置label值之后,再來(lái)看debug=1后的網(wǎng)頁(yè)輸出,可以發(fā)現(xiàn) 設(shè)置的labels出現(xiàn)了。

1 @ 0x104f86c60 0x104fb7358 0x105236368 0x104f867ec 0x104fba024 # labels: {"age":"18", "name":"lanpangzi"} # 0x104fb7357 time.Sleep+0x137 /Users/xiongchuanhong/goproject/src/go/src/runtime/time.go:193 # 0x105236367 main.main+0x437  /Users/xiongchuanhong/goproject/src/go/main/main.go:46 # 0x104f867eb runtime.main+0x25b /Users/xiongchuanhong/goproject/src/go/src/runtime/proc.go:255

而數(shù)字1之后,就是協(xié)程正在執(zhí)行的函數(shù)堆棧信息了。

使用二進(jìn)制文件查看

我們可以通過(guò)如下代碼生成profile的二進(jìn)制文件,在下述代碼中,我生成了兩個(gè)協(xié)程,然后開(kāi)啟對(duì)goroutine指標(biāo)的采集。

package main  
  
import (  
    "fmt"  
    "github.com/pkg/profile"    
    "time")  
  
func main() {  
    go mockGo()  
    go mockGo()  
    p := profile.Start(profile.GoroutineProfile,  
       profile.ProfilePath("profile"),  
       profile.NoShutdownHook)  
    p.Stop()  
}  
  
func mockGo() {  
    time.Sleep(time.Second * 3)  
    fmt.Println("獲取鎖")  
}

生成的goroutine二進(jìn)制文件后,查看goroutine 方式也和其他profile指標(biāo)一致,這里我直接放上通過(guò)web瀏覽器查看的graph。 顯示的堆棧信息為當(dāng)前程序中協(xié)程正在執(zhí)行的堆棧,可以看到main.mockGo 函數(shù)中有兩個(gè)協(xié)程在執(zhí)行這個(gè)方法,main方法中一個(gè)協(xié)程在執(zhí)行。

圖片圖片

thread

http接口暴露的控制臺(tái)查看

介紹完goroutine指標(biāo)的輸出信息后,再來(lái)看看threadcreate 線(xiàn)程創(chuàng)建指標(biāo)的 輸出信息。先來(lái)看下在控制臺(tái)中通過(guò)點(diǎn)擊thread鏈接看到的輸出。

圖片圖片

老規(guī)矩,先看地址欄,debug=1代表 輸出的是文本可讀的信息,threadcreate 就沒(méi)有debug=2的特別輸出了,debug=0時(shí) 同樣也會(huì)下載一個(gè)可供go tool pprof分析的二進(jìn)制文件。

接著threadcreate pfofile表明了profile的類(lèi)型。

total 12 代表了此時(shí)總共有12個(gè)線(xiàn)程被創(chuàng)建。

11 代表了在這個(gè)總共有11個(gè)線(xiàn)程是在這個(gè)堆棧的代碼段上被創(chuàng)建的,注意這里后面沒(méi)有堆棧內(nèi)容,說(shuō)明runtime在創(chuàng)建線(xiàn)程時(shí),并沒(méi)有把此時(shí)的堆棧記錄下來(lái),原因有可能是 這個(gè)線(xiàn)程是runtime自己使用的,堆棧沒(méi)有必要展示給用戶(hù),所以干脆不記錄了,具體原因這里就不深入研究了。

上面輸出的內(nèi)容可以看到在main方法里面創(chuàng)建了一個(gè)線(xiàn)程,runtime.newm 方法內(nèi)部,runtime會(huì)啟動(dòng)一個(gè)系統(tǒng)線(xiàn)程。

使用二進(jìn)制文件查看

在代碼中開(kāi)始采集thread的信息,生成二進(jìn)制文件可以采用以下代碼,和goroutine示例代碼類(lèi)似,不同的是改變采集的指標(biāo)對(duì)象,改成了ThreadcreationProfile。

package main  
  
import (  
    "fmt"  
    "github.com/pkg/profile"    
    "time")  
  
func main() {  
    go mockGo()  
    go mockGo()  
    p := profile.Start(profile.ThreadcreationProfile,  
       profile.ProfilePath("profile"),  
       profile.NoShutdownHook)  
    p.Stop()  
}  
  
func mockGo() {  
    time.Sleep(time.Second * 3)  
    fmt.Println("獲取鎖")  
}

生成的二進(jìn)制文件通過(guò) go tool pprof -http=:8083 ../profile/threadcreation.pprof 啟動(dòng)瀏覽器窗口查看其graph,如下是線(xiàn)程的graph,圖中的堆棧信息是創(chuàng)建線(xiàn)程時(shí)的堆棧信息。

圖片圖片


責(zé)任編輯:武曉燕 來(lái)源: 藍(lán)胖子的編程夢(mèng)
相關(guān)推薦

2021-10-18 11:58:56

負(fù)載均衡虛擬機(jī)

2022-09-06 08:02:40

死鎖順序鎖輪詢(xún)鎖

2021-01-19 05:49:44

DNS協(xié)議

2022-09-14 09:01:55

shell可視化

2022-03-28 10:56:11

Python字符串格式化

2020-07-15 08:57:40

HTTPSTCP協(xié)議

2020-11-16 10:47:14

FreeRTOS應(yīng)用嵌入式

2023-06-12 08:49:12

RocketMQ消費(fèi)邏輯

2022-07-19 16:03:14

KubernetesLinux

2020-07-09 07:54:35

ThreadPoolE線(xiàn)程池

2022-10-10 08:35:17

kafka工作機(jī)制消息發(fā)送

2024-05-10 12:59:58

PyTorch人工智能

2024-01-11 09:53:31

面試C++

2022-09-08 10:14:29

人臉識(shí)別算法

2024-01-05 08:30:26

自動(dòng)駕駛算法

2021-08-26 05:02:50

分布式設(shè)計(jì)

2022-07-15 16:31:49

Postman測(cè)試

2021-06-04 07:27:24

sourcemap前端技術(shù)

2022-04-25 10:56:33

前端優(yōu)化性能

2022-02-15 18:45:35

Linux進(jìn)程調(diào)度器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

少妇愉情理伦三级| 成人久久一区二区| 噜噜噜在线视频| 欧美电影免费观看| 欧美国产一区二区在线观看| 成人福利在线视频| 亚洲精品视频在线观看免费视频| 国产91精品对白在线播放| www.欧美日本韩国| 美女爽到高潮91| 欧美黄色片视频| 男人天堂av电影| 久久99成人| 91高清在线观看| 国产在线无码精品| 高清毛片在线看| 国产成人av自拍| 国产精品久久久久久久久久尿 | 国产免费一区二区三区| 日本视频网站在线观看| 女人天堂亚洲aⅴ在线观看| 日韩电影中文 亚洲精品乱码| 超碰在线97免费| av老司机在线观看| 亚洲欧美一区二区视频| 久久久久久久免费| 亚洲第一精品网站| 久久精品国内一区二区三区| 97视频人免费观看| 草视频在线观看| 日韩成人影院| 国产午夜精品一区理论片飘花| 国产伦理在线观看| 国产精品2区| 欧美性大战xxxxx久久久| 青青青国产在线观看| 亚洲xxx在线观看| 高清毛片在线看| 97久久超碰国产精品电影| 成人网在线免费看| 亚洲精品国产系列| 成人一级生活片| 中文字幕日本在线观看| 久久婷婷色综合| 亚洲成人激情图| 国产99午夜精品一区二区三区| 天天干天天操天天操| 亚洲另类自拍| 欧美日韩高清在线观看| frxxee中国xxx麻豆hd| 欧洲毛片在线视频免费观看| 香蕉成人久久| 欧美成人亚洲成人日韩成人| 日韩精品久久久久久久的张开腿让| 丝袜美腿综合| 亚洲免费电影一区| 麻豆av免费观看| 免费久久精品| 亚洲人成绝费网站色www| 99热国产在线观看| 日本黄色免费在线| 亚洲国产成人av| 日本a在线天堂| 免费污视频在线| 亚洲国产一区二区a毛片| 国产美女主播在线| а√天堂中文资源在线bt| 亚洲亚洲人成综合网络| 97视频在线免费| 天堂av在线| 欧美在线一二三四区| 色悠悠久久综合网| 91精品一久久香蕉国产线看观看 | 97se亚洲国产综合自在线| 国产伦精品一区二区| 亚洲 欧美 激情 另类| 久久理论电影网| 亚洲高清视频一区二区| 男人影院在线观看| 一区二区免费看| a√天堂在线观看| 99久久伊人| 日韩欧美黄色影院| 亚洲成人网在线播放| 欧美成人直播| 国模精品系列视频| 精产国品一区二区| 国产一区二区在线看| 国产无套精品一区二区| 激情视频在线观看免费| 亚洲啪啪综合av一区二区三区| 欧美精品在欧美一区二区| 国产精品专区免费| 91麻豆精品国产综合久久久久久| 在线中文字日产幕| 精品国产一区二区三区香蕉沈先生| 久久精品国产69国产精品亚洲| 国产亚洲成人精品| 日韩福利视频网| 成人精品一二区| 国产精品99999| 亚洲国产精品视频| 美女网站色免费| 国产欧美三级电影| 日韩中文字在线| www.毛片.com| 国产美女一区二区三区| 欧美色欧美亚洲另类七区| 黄网站视频在线观看| 欧美天天综合色影久久精品| 加勒比av中文字幕| 国产成人黄色| 久久久久久69| 97人妻一区二区精品免费视频 | 色爱综合区网| 欧美三级三级三级爽爽爽| 中国黄色片视频| 久久久久久久久国产一区| 热久久免费视频精品| www天堂在线| 国产精品日韩成人| 成人在线看视频| 韩国女主播一区二区三区| 一区二区三欧美| 国产精品美女久久久久av爽| 国产精品一区三区| 亚洲一区二区三区加勒比| av日韩电影| 亚洲精品国产精品乱码不99按摩| av激情在线观看| 麻豆国产精品777777在线| 欧美国产一二三区| 伊人网在线播放| 亚洲精品一区在线观看| 外国一级黄色片| 国内成人免费视频| 亚洲一区二区三区色| 亚洲电影有码| 亚洲性猛交xxxxwww| 久久久久久不卡| 久久天天做天天爱综合色| 大j8黑人w巨大888a片| 国产精品白丝av嫩草影院| 九九视频直播综合网| 99国产成人精品| 亚洲欧美另类图片小说| 精品综合久久久久| 国产精品久久久久久影院8一贰佰 国产精品久久久久久麻豆一区软件 | 黑人精品一区二区三区| 亚洲另类在线视频| 日本一二三四区视频| 亚洲精品二区三区| 91网站免费观看| 羞羞的网站在线观看| 欧美一区二区观看视频| 欧美日韩在线观看成人| 国产精品性做久久久久久| 日本黄网站色大片免费观看| 91久久偷偷做嫩草影院电| 欧美激情2020午夜免费观看| 国模无码一区二区三区| 亚洲大片精品永久免费| 日本黄色免费观看| 亚洲专区一区二区三区| 日本在线高清视频一区| 精品久久在线| 不卡av在线网站| 人妻少妇精品无码专区久久| 狠狠躁夜夜躁久久躁别揉| 无码 人妻 在线 视频| 免费av网站大全久久| 亚洲免费视频播放| 97久久亚洲| 啪一啪鲁一鲁2019在线视频| a中文在线播放| 日韩一级大片在线观看| 福利一区二区三区四区| 久久久国产一区二区三区四区小说| 久久综合久久色| 久久久9色精品国产一区二区三区| 91精品婷婷国产综合久久蝌蚪| 国产探花在线观看| 亚洲男人的天堂在线| 国产永久免费视频| 亚洲国产精品久久久男人的天堂| 熟女高潮一区二区三区| 国内欧美视频一区二区| 国产 日韩 欧美在线| 欧美丝袜丝交足nylons172| 国产一区二区丝袜| 成av人片在线观看www| 中文字幕日韩av| 成人午夜视频一区二区播放| 91成人免费网站| 久久久国产精品黄毛片| 久久久不卡网国产精品二区| 中文字幕avav| 日韩国产欧美三级| 人人妻人人做人人爽| 日本不卡免费一区| 国产专区一区二区| 一区二区三区日本视频| 欧美与黑人午夜性猛交久久久| 国内外激情在线| 精品中文字幕久久久久久| 99草在线视频| 欧美午夜免费电影| 日韩人妻无码一区二区三区99| 国产精品久久久久一区二区三区共| www国产视频| 国模大尺度一区二区三区| 草草草在线视频| 黄色成人av网站| 三年中文高清在线观看第6集| 夜色77av精品影院| 国产日韩一区二区三区| 秋霞午夜一区二区三区视频| 国产激情综合五月久久| 三级在线观看视频| 久久久久久久亚洲精品| 国产福利在线播放麻豆| 正在播放欧美视频| 青青草超碰在线| 日韩成人在线网站| 高清国产mv在线观看| 宅男在线国产精品| 国产乱码一区二区| 丰满熟妇乱又伦| 国产在线精品免费av| 国产免费毛卡片| 欧美日韩p片| 欧美三级日本三级少妇99| 国产真实的和子乱拍在线观看| 中文成人综合网| 五月婷婷综合在线观看| www.色精品| 人妻 丝袜美腿 中文字幕| 激情六月婷婷综合| 日韩中文字幕a| 免费看黄色91| 日日噜噜夜夜狠狠| 秋霞午夜av一区二区三区| 成年人网站大全| 久久久久在线| 国产免费视频传媒| 人人狠狠综合久久亚洲| 久久黄色免费看| 日韩av中文字幕一区二区三区 | 亚洲欧洲午夜| 欧美成人精品免费| 亚洲美女少妇无套啪啪呻吟| 国产欧美日韩网站| av不卡免费看| 日批视频在线免费看| 国内精品久久久久久久97牛牛| 欧美成人精品一区二区三区| 色的视频在线免费看| 日韩亚洲成人av在线| 国产免费av高清在线| 国产主播在线一区| 欧美偷拍视频| 日韩精品免费视频| 欧美欧美欧美| 亚洲偷熟乱区亚洲香蕉av| 美女国产一区| 欧美中文在线观看| 亚洲天堂手机| 国产精品成人在线| 国产精品无码永久免费不卡| 国产91精品露脸国语对白| av在线天堂网| av亚洲精华国产精华| 搡老熟女老女人一区二区| 久久久久久久久免费| 少妇精品无码一区二区免费视频 | 91中文字幕永久在线| 国产日韩欧美综合在线| 91香蕉视频网| 亚洲国产日韩一级| 天堂网一区二区| 91精品综合久久久久久| 天天摸天天碰天天爽天天弄| 亚洲人成欧美中文字幕| 天堂аⅴ在线地址8| 欧美国产乱视频| 成人性生交大片免费观看网站| 国产精品久久久久影院日本| 日本高清久久| 久久精品中文字幕一区二区三区| 黄色不卡一区| 久久香蕉视频网站| 丝袜美腿成人在线| 日韩欧美中文在线视频| 91老师国产黑色丝袜在线| 免费在线观看a视频| 亚洲制服丝袜av| 亚洲大尺度在线观看| 精品日韩一区二区三区免费视频| 欧美巨乳在线| 欧美福利视频网站| 高清av一区二区三区| 精品国产aⅴ麻豆| 国产精品久久久久蜜臀| 久久久久久久久久久久久久国产| 国产中文一区二区三区| 男人天堂av电影| 亚洲午夜免费电影| 91国内精品视频| 亚洲欧美国产日韩天堂区| 日本一本在线免费福利| 国产精品第一区| 老司机精品视频在线播放| 国产高清精品软男同| 日韩主播视频在线| 26uuu国产| 中文字幕亚洲一区二区va在线| 可以在线观看av的网站| 日韩欧美电影在线| 欧美精品电影| 国产精品流白浆视频| 日韩欧美黄色| 99色这里只有精品| 国产精品一区久久久久| 久久久久久久久福利| 欧美视频专区一二在线观看| 欧美一区二区三区黄片| 蜜臀久久99精品久久久无需会员| 99久久亚洲国产日韩美女| 美乳视频一区二区| 国产情侣一区| 亚洲欧美在线不卡| 亚洲成人午夜影院| 亚洲爆乳无码一区二区三区| www.欧美三级电影.com| 黄页免费欧美| 亚洲国内在线| 男女男精品视频| 色欲AV无码精品一区二区久久| 狠狠综合久久av一区二区小说| 色网站免费观看| 91黑丝高跟在线| 日韩mv欧美mv国产网站| 成人黄色av片| www亚洲一区| 麻豆久久久久久久久久| 日韩精品视频在线播放| 悠悠资源网亚洲青| 另类欧美小说| 三级亚洲高清视频| 极品久久久久久久| 欧美午夜影院一区| 欧美激情午夜| 亚洲va欧美va在线观看| 你懂的网址国产 欧美| 亚洲欧美一区二区三区情侣bbw| 在线观看免费版| 国产精品亚洲аv天堂网| 操欧美老女人| 手机看片一级片| 日韩一区中文字幕| xxxx18国产| 欧美色婷婷久久99精品红桃| 日韩男女性生活视频| 精品亚洲成人| 亚洲一区二区三区观看| 亚洲激情六月丁香| 丰满人妻一区二区三区免费| 久久琪琪电影院| 沈樵精品国产成av片| 天天操狠狠操夜夜操| 亚洲精品成人天堂一二三| 神马一区二区三区| 国产精品白嫩初高中害羞小美女| 999久久久亚洲| 四虎永久免费观看| 色综合久久综合网欧美综合网| av在线播放网站| 91久久精品国产91久久性色tv | 国产精品久久中文字幕| 久久亚洲一区二区三区四区| 18国产免费视频| 欧美激情一区二区三区在线视频观看 | 日韩中文字幕免费看| 国产一二三四五区| 在线观看国产日韩| 黄色网页网址在线免费| 97夜夜澡人人双人人人喊| 在线看片一区| 国产伦精品一区二区三区视频女| 在线成人av网站| 日韩伦理精品| 婷婷视频在线播放| www.亚洲免费av| 亚洲视频一区在线播放| 欧美国产视频一区二区| 国产成人一区| 亚洲av无码成人精品区| 色老综合老女人久久久| 9191在线播放| 日本一区二区三区免费看|