欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

gopprof如何使用

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

公司主營業(yè)務(wù):成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)公司推出吉木乃免費(fèi)做網(wǎng)站回饋大家。

pprof是Go的性能分析工具,在程序運(yùn)行過程中,可以記錄程序的運(yùn)行信息,可以是CPU使用情況、內(nèi)存使用情況、goroutine運(yùn)行情況等,當(dāng)需要性能調(diào)優(yōu)或者定位Bug時候,這些記錄的信息是相當(dāng)重要。使用pprof有多種方式,Go已經(jīng)現(xiàn)成封裝好了1個“net/http/pprof”,使用簡單的幾行命令,就可以開啟pprof,記錄運(yùn)行信息,并且提供了Web服務(wù)。

go pprof簡介

profile 一般被稱為 性能分析,詞典上的翻譯是 概況(名詞)或者 描述…的概況(動詞)。對于計(jì)算機(jī)程序來說,它的 profile,就是一個程序在運(yùn)行時的各種概況信息,包括 cpu 占用情況,內(nèi)存情況,線程情況,線程阻塞情況等等。知道了程序的這些信息,也就能容易的定位程序中的問題和故障原因 。

pprof是Go的性能分析工具,在程序運(yùn)行過程中,可以記錄程序的運(yùn)行信息,可以是CPU使用情況、內(nèi)存使用情況、goroutine運(yùn)行情況等,當(dāng)需要性能調(diào)優(yōu)或者定位Bug時候,這些記錄的信息是相當(dāng)重要。

golang 對于 profiling 支持的比較好,標(biāo)準(zhǔn)庫就提供了profile庫 “runtime/pprof” 和 “net/http/pprof”,而且也提供了很多好用的可視化工具來輔助開發(fā)者做 profiling。

對于在線服務(wù),對于一個 HTTP Server,訪問 pprof 提供的 HTTP 接口,獲得性能數(shù)據(jù)。當(dāng)然,實(shí)際上這里底層也是調(diào)用的 runtime/pprof 提供的函數(shù),封裝成接口對外提供網(wǎng)絡(luò)訪問,本文主要介紹"net/http/pprof"的使用。

基本使用

使用pprof有多種方式,Go已經(jīng)現(xiàn)成封裝好了1個:net/http/pprof,使用簡單的幾行命令,就可以開啟pprof,記錄運(yùn)行信息,并且提供了Web服務(wù),能夠通過瀏覽器和命令行2種方式獲取運(yùn)行數(shù)據(jù)。

web服務(wù)中如何開啟監(jiān)控,來看一個簡單的例子。

package main

import (
"fmt"
 "net/http"
 _ "net/http/pprof"
)

func main() {
// 開啟pprof,監(jiān)聽請求
 ip := "0.0.0.0:8080"
 if err := http.ListenAndServe(ip, nil); err != nil {
 	fmt.Printf("start pprof failed on %s\n", ip)
 }
 dosomething()
}

在程序中導(dǎo)入 "net/http/pprof"包,并打開監(jiān)聽端口,這時候便可以獲取程序的profile,在實(shí)際生產(chǎn)中,我們一般將這個功能封裝成一個goroutine。那么開啟之后如何查看呢?有三種方式:

瀏覽器方式

打開一個瀏覽器輸入 ip:port/debug/pprof,回車。

go pprof如何使用

pprof會提供很多性能數(shù)據(jù)。具體含義為:

  • allocs:內(nèi)存分配情況的采樣信息

  • blocks:阻塞操作情況的采樣信息 cmdline:程序啟動命令及其參數(shù)

  • goroutine:當(dāng)前所有協(xié)程的堆棧信息

  • heap:堆上內(nèi)存的使用情況的采樣信息 mutex:鎖爭用情況的采樣信息

  • profile:cpu占用情況的采樣信息

  • threadcreate:系統(tǒng)線程創(chuàng)建情況的采樣信息

  • trace:程序運(yùn)行的跟蹤信息

allocs是所有對象的內(nèi)存分配,heap是活躍對象的內(nèi)存分配,后文會有詳細(xì)的描述。

1、當(dāng) CPU 性能分析啟用后,Go runtime 會每 10ms 就暫停一下,記錄當(dāng)前運(yùn)行的 goroutine 的調(diào)用堆棧及相關(guān)數(shù)據(jù)。當(dāng)性能分析數(shù)據(jù)保存到硬盤后,我們就可以分析代碼中的熱點(diǎn)了。
2、內(nèi)存性能分析則是在堆(Heap)分配的時候,記錄一下調(diào)用堆棧。默認(rèn)情況下,是每 1000 次分配,取樣一次,這個數(shù)值可以改變。棧(Stack)分配 由于會隨時釋放,因此不會被內(nèi)存分析所記錄。由于內(nèi)存分析是取樣方式,并且也因?yàn)槠溆涗浀氖欠峙鋬?nèi)存,而不是使用內(nèi)存。因此使用內(nèi)存性能分析工具來準(zhǔn)確判斷程序具體的內(nèi)存使用是比較困難的。
3、阻塞分析是一個很獨(dú)特的分析,它有點(diǎn)兒類似于 CPU 性能分析,但是它所記錄的是 goroutine 等待資源所花的時間。阻塞分析對分析程序并發(fā)瓶頸非常有幫助,阻塞性能分析可以顯示出什么時候出現(xiàn)了大批的 goroutine 被阻塞了。阻塞性能分析是特殊的分析工具,在排除 CPU 和內(nèi)存瓶頸前,不應(yīng)該用它來分析。

當(dāng)然,如果你點(diǎn)進(jìn)任何一個鏈接,便會發(fā)現(xiàn),可讀性差,幾乎無法分析。如圖:

go pprof如何使用

點(diǎn)擊heap,拉到最底部,可以看到一些有意思的數(shù)據(jù),有時候也有可能會對問題排查有幫助,但一般不用。

heap profile: 3190: 77516056 [54762: 612664248] @ heap/1048576
1: 29081600 [1: 29081600] @ 0x89368e 0x894cd9 0x8a5a9d 0x8a9b7c 0x8af578 0x8b4441 0x8b4c6d 0x8b8504 0x8b2bc3 0x45b1c1
#    0x89368d    github.com/syndtr/goleveldb/leveldb/memdb.(*DB).Put+0x59d
#    0x894cd8    xxxxx/storage/internal/memtable.(*MemTable).Set+0x88
#    0x8a5a9c    xxxxx/storage.(*snapshotter).AppendCommitLog+0x1cc
#    0x8a9b7b    xxxxx/storage.(*store).Update+0x26b
#    0x8af577    xxxxx/config.(*config).Update+0xa7
#    0x8b4440    xxxxx/naming.(*naming).update+0x120
#    0x8b4c6c    xxxxx/naming.(*naming).instanceTimeout+0x27c
#    0x8b8503    xxxxx/naming.(*naming).(xxxxx/naming.instanceTimeout)-fm+0x63

......

# runtime.MemStats
# Alloc = 2463648064
# TotalAlloc = 31707239480
# Sys = 4831318840
# Lookups = 2690464
# Mallocs = 274619648
# Frees = 262711312
# HeapAlloc = 2463648064
# HeapSys = 3877830656
# HeapIdle = 854990848
# HeapInuse = 3022839808
# HeapReleased = 0
# HeapObjects = 11908336
# Stack = 655949824 / 655949824
# MSpan = 63329432 / 72040448
# MCache = 38400 / 49152
# BuckHashSys = 1706593
# GCSys = 170819584
# OtherSys = 52922583
# NextGC = 3570699312
# PauseNs = [1052815 217503 208124 233034 ......]
# NumGC = 31
# DebugGC = false

  • Sys: 進(jìn)程從系統(tǒng)獲得的內(nèi)存空間,虛擬地址空間

  • HeapAlloc:進(jìn)程堆內(nèi)存分配使用的空間,通常是用戶new出來的堆對象,包含未被gc掉的。

  • HeapSys:進(jìn)程從系統(tǒng)獲得的堆內(nèi)存,因?yàn)間olang底層使用TCmalloc機(jī)制,會緩存一部分堆內(nèi)存,虛擬地址空間

  • PauseNs:記錄每次gc暫停的時間(納秒),最多記錄256個最新記錄。

  • NumGC: 記錄gc發(fā)生的次數(shù)

命令行方式

除了瀏覽器,Go還提供了命令行的方式,能夠獲取以上信息,這種方式用起來更方便。

使用命令go tool pprof url可以獲取指定的profile文件,此命令會發(fā)起http請求,然后下載數(shù)據(jù)到本地,之后進(jìn)入交互式模式,就像gdb一樣,可以使用命令查看運(yùn)行信息,以下為使用示例:

# 下載cpu profile,默認(rèn)從當(dāng)前開始收集30s的cpu使用情況,需要等待30s
go tool pprof http://localhost:8080/debug/pprof/profile # 30-second CPU profile
go tool pprof http://localhost:8080/debug/pprof/profile?seconds=120 # wait 120s

# 下載heap profile
go tool pprof http://localhost:8080/debug/pprof/heap # heap profile

# 下載goroutine profile
go tool pprof http://localhost:8080/debug/pprof/goroutine # goroutine profile

# 下載block profile
go tool pprof http://localhost:8080/debug/pprof/block # goroutine blocking profile

# 下載mutex profile
go tool pprof http://localhost:8080/debug/pprof/mutex

接下來用一個例子來說明最常用的四個命令:web、top、list、traces。

接下來以內(nèi)存分析舉例,cpu和goroutine等分析同理,讀者可以自行舉一反三。

首先,我們通過命令go tool pprof url獲取指定的profile/heap文件,隨后自動進(jìn)入命令行。如圖:

go pprof如何使用

第一步,我們首先輸入web命令,這時瀏覽器會彈出各個函數(shù)之間的調(diào)用圖,以及內(nèi)存的之間的關(guān)系。如圖:

go pprof如何使用

這個圖的具體讀法,可參照:中文文檔 或者英文文檔 這里不多贅述。只需要了解越紅越大的方塊,有問題的可能性就越大,代表可能占用了更多的內(nèi)存,如果在cpu的圖中代表消耗了更多cpu資源,以此類推。
接下來 top、list、traces三步走可以看出很多想要的結(jié)果。

top按指標(biāo)大小列出前10個函數(shù),比如內(nèi)存是按內(nèi)存占用多少,CPU是按執(zhí)行時間多少。
top會列出5個統(tǒng)計(jì)數(shù)據(jù):

  • flat: 本函數(shù)占用的內(nèi)存量。

  • flat%: 本函數(shù)內(nèi)存占使用中內(nèi)存總量的百分比。

  • sum%: 之前函數(shù)flat的累計(jì)和。

  • cum:是累計(jì)量,假如main函數(shù)調(diào)用了函數(shù)f,函數(shù)f占用的內(nèi)存量,也會記進(jìn)來。

  • cum%: 是累計(jì)量占總量的百分比。

go pprof如何使用

這樣我們可以看到到底是具體哪些函數(shù)占用了多少內(nèi)存。

當(dāng)然top后也可以接參數(shù),top n可以列出前n個函數(shù)。

list可以查看某個函數(shù)的代碼,以及該函數(shù)每行代碼的指標(biāo)信息,如果函數(shù)名不明確,會進(jìn)行模糊匹配,比如list main會列出main.mainruntime.main?,F(xiàn)在list sendToASR試一下。

go pprof如何使用

可以看到切片中增加元素時,占用了很多內(nèi)存,左右2個數(shù)據(jù)分別是flatcum。

traces打印所有調(diào)用棧,以及調(diào)用棧的指標(biāo)信息。使用方式為traces+函數(shù)名(模糊匹配)。

go pprof如何使用

在命令行之中,還有一個重要的參數(shù) -base,假設(shè)我們已經(jīng)通過命令行得到profile1與profile2,使用go tool pprof -base profile1 profile2,便可以以profile1為基礎(chǔ),得出profile2在profile1之上出現(xiàn)了哪些變化。通過兩個時間切片的比較,我們可以清晰的了解到,兩個時間節(jié)點(diǎn)之中發(fā)生的變化,方便我們定位問題(很重要?。。。。?/p>

可視化界面

打開可視化界面的方式為:go tool pprof -http=:1234 http://localhost:8080/debug/pprof/heap 其中1234是我們指定的端口

go pprof如何使用

Top

go pprof如何使用

該視圖與前面所講解的 top 子命令的作用和含義是一樣的,因此不再贅述。

Graph

為函數(shù)調(diào)用圖,不在贅述.

Peek

go pprof如何使用

此視圖相較于 Top 視圖,增加了所屬的上下文信息的展示,也就是函數(shù)的輸出調(diào)用者/被調(diào)用者。

Source

go pprof如何使用

該視圖主要是增加了面向源代碼的追蹤和分析,可以看到其開銷主要消耗在哪里。

Flame Graph

go pprof如何使用

對應(yīng)資源消耗的火焰圖,火焰圖的讀法,這里不贅述,不是本文的重點(diǎn)。

第二個下拉菜單如圖所示:

go pprof如何使用

alloc_objects,alloc_space表示應(yīng)用程序分配過的資源,不管有沒有釋放,inuse_objects,inuse_space表示應(yīng)用程序的還未釋放的資源常配情況。

NameMeaning
inuse_spaceamount of memory allocated and not released yet
inuse_objectsamount of objects allocated and not released yet
alloc_spacetotal amount of memory allocated (regardless of released)
alloc_objectstotal amount of objects allocated (regardless of released)

第一個下拉菜單可以與第二個下拉菜單相組合,可以查看臨時變量的火焰圖,常駐變量的內(nèi)存調(diào)用圖等。

tips

  • 程序運(yùn)行占用較大的內(nèi)存,可以通過 inuse_space 來體現(xiàn).

  • 存在非常頻繁的 GC 活動,通常意味著 alloc_space非常高,而程序運(yùn)行過程中并沒有消耗太多的內(nèi)存(體現(xiàn)為 inuse_space 并不高),當(dāng)然也可能出現(xiàn) GC 來不及回收,因此c出現(xiàn)inuse_space 也變高的情況。這種情況下同樣會大量消耗CPU。

  • 內(nèi)存泄漏,通常 alloc_space 較高,且
    inuse_space 也較高。

操作方法

上面我們已經(jīng)看完了go pprof 的所有操作,接下來講解一下go tool pprof 的具體使用流程。

  • 通過監(jiān)控平臺監(jiān)測到內(nèi)存或cpu問題。

  • 通過瀏覽器方式大致判斷是哪些可能的問題。

  • 通過命令行方式抓取幾個時間點(diǎn)的profile

  • 使用web命令查看函數(shù)調(diào)用圖

  • 使用top 、traces、list 命令定位問題

  • 如果出現(xiàn)了goroutine泄漏或者內(nèi)存泄漏等隨著時間持續(xù)增長的問題,go tool pprof -base比較兩個不同時間點(diǎn)的狀態(tài)更方便我們定位問題。

具體案例

案例一:goroutine泄漏

啟動程序后,用瀏覽器方式打開profile:

go pprof如何使用

發(fā)現(xiàn)內(nèi)存持續(xù)上升,同時goroutine也在持續(xù)上升,初步判斷,內(nèi)存泄漏是由于goroutine泄漏導(dǎo)致的。

接下來通過命令行方式抓取goroutine的情況:命令行輸入:go tool pprof localhost:8080/debug/pprof/goroutine,獲取結(jié)果。

分析的流程

一、使用web命令查看調(diào)用圖,大概了解目前的goroutine的泄露情況:

go pprof如何使用

通過觀察,最引入注目的便是runtime.gopark這個函數(shù),這個函數(shù)在所有g(shù)oroutine泄漏時都會出現(xiàn),并且是大頭,接下來我們研究一下這個函數(shù)的作用:

func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason waitReason, traceEv byte, traceskip int) {
 mp := acquirem()
 gp := mp.curg
 status := readgstatus(gp)
 mp.waitlock = lock
 mp.waitunlockf = unlockf
 gp.waitreason = reason
 mp.waittraceev = traceEv
 mp.waittraceskip = traceskip
 releasem(mp)
 
 mcall(park_m)
}

該函數(shù)的作用為:

1、調(diào)用acquirem函數(shù):獲取當(dāng)前goroutine所綁定的m,設(shè)置各類所需參數(shù)。調(diào)用 releasem 函數(shù)將當(dāng)前 goroutine 和其 m 的綁定關(guān)系解除。

2、調(diào)用 park_m 函數(shù):將當(dāng)前 goroutine 的狀態(tài)從 _Grunning 切換為 _Gwaiting,也就是等待狀態(tài)。刪除 m 和當(dāng)前 goroutine m→curg(簡稱gp)之間的關(guān)聯(lián)。

3、調(diào)用 mcall 函數(shù),僅會在需要進(jìn)行 goroutiine 切換時會被調(diào)用:切換當(dāng)前線程的堆棧,從 g 的堆棧切換到 g0 的堆棧并調(diào)用 fn(g) 函數(shù)。將 g 的當(dāng)前 PC/SP 保存在 g->sched 中,以便后續(xù)調(diào)用 goready 函數(shù)時可以恢復(fù)運(yùn)行現(xiàn)場。

綜上:該函數(shù)的關(guān)鍵作用就是將當(dāng)前的 goroutine 放入等待狀態(tài),這意味著 goroutine 被暫時被擱置了,也就是被運(yùn)行時調(diào)度器暫停了。
所以出現(xiàn)goroutine泄漏一定會調(diào)用這個函數(shù),這個函數(shù)不是goroutine泄漏的原因,而是goroutine泄漏的結(jié)果。

此外,我們發(fā)現(xiàn)有兩個函數(shù)的goroutine的達(dá)到了67,很可疑,在我們接下來的驗(yàn)證中要格外留意。

二、使用top命令,獲取更加具體的函數(shù)信息:

go pprof如何使用

與上面分析的結(jié)論相似,我們要將關(guān)注點(diǎn)放在三個開啟了67個goroutine的函數(shù)。

三、traces+函數(shù)名,查看調(diào)用棧,這一步在函數(shù)調(diào)用很復(fù)雜,無法從調(diào)用圖里面清晰的看出時使用,幫助我們更清晰的了解函數(shù)的調(diào)用堆棧:

go pprof如何使用

四、使用list+函數(shù)名,查看具體代碼的問題。

go pprof如何使用

go pprof如何使用

通過list命令我們可以清楚的看出問題代碼是堵塞在哪里。

goroutine泄漏知識

什么是goroutine泄漏:如果你啟動了一個 goroutine,但并沒有符合預(yù)期的退出,直到程序結(jié)束,此goroutine才退出,這種情況就是 goroutine 泄露。當(dāng) goroutine 泄露發(fā)生時,該 goroutine 的棧(一般 2k 內(nèi)存空間起)一直被占用不能釋放,goroutine 里的函數(shù)在堆上申請的空間也不能被 垃圾回收器 回收。這樣,在程序運(yùn)行期間,內(nèi)存占用持續(xù)升高,可用內(nèi)存越來也少,最終將導(dǎo)致系統(tǒng)崩潰。
什么時候出現(xiàn)goroutine泄漏:goroutine泄露一般是因?yàn)閏hannel操作阻塞而導(dǎo)致整個routine一直阻塞等待或者 goroutine 里有死循環(huán)。
具體細(xì)分一下:

  • 從 channel 里讀,但是沒有寫。

  • 向 unbuffered channel 寫,但是沒有讀。

  • 向已滿的 buffered channel 寫,但是沒有讀。

  • select操作在所有case上阻塞。

  • goroutine進(jìn)入死循環(huán)中,導(dǎo)致資源一直無法釋放。

select底層也是channel實(shí)現(xiàn)的,如果所有case上的操作阻塞,select內(nèi)部的channel便會阻塞,goroutine也無法繼續(xù)執(zhí)行。所以我們使用channel時一定要格外小心。

通過分析上面兩幅圖的情況,可以判斷是因?yàn)閟elect在所有case上死鎖了,再深入代碼分析,是因?yàn)轫?xiàng)目中的的語音模型并發(fā)能力弱,在語音發(fā)包速度快起來的時候無法處理,導(dǎo)致select不滿足條件,導(dǎo)致goroutine泄漏,應(yīng)該在for循環(huán)之外加一個asr←nil,保證func2的select一定會滿足,同時提高模型的并發(fā)能力,使得func1的不會阻塞。
防止goroutine泄漏的建議:

  • 創(chuàng)建goroutine時就要想好該goroutine該如何結(jié)束。

  • 使用channel時,要考慮到 channel阻塞時協(xié)程可能的行為,是否會創(chuàng)建大量的goroutine。

  • goroutine中不可以存在死循環(huán)。

案例二:內(nèi)存泄漏

我們通過grafana發(fā)現(xiàn)內(nèi)存出現(xiàn)泄漏:

go pprof如何使用

這一次我們不使用命令行,而是使用圖形化界面來定位問題。
輸入 go tool pprof -http=:1234 localhost:8080/debug/pprof/heap:

go pprof如何使用發(fā)現(xiàn)內(nèi)存占用很有可能是byte.makeSlice()導(dǎo)致的,火焰圖看的更加清晰:

go pprof如何使用

而調(diào)用byte.makeSlice()的函數(shù)為標(biāo)準(zhǔn)庫中的ioutil.ReadAll(),接下來我們只需要研究這個標(biāo)準(zhǔn)庫函數(shù)的實(shí)現(xiàn)即可。

func readAll(r io.Reader, capacity int64) (b []byte, err error) {
	buf := bytes.NewBuffer(make([]byte, 0, capacity))
	defer func() {
		e := recover()
		if e == nil {
			return
		}
		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
			err = panicErr
		} else {
			panic(e)
		}
	}()
	_, err = buf.ReadFrom(r)
	return buf.Bytes(), err
}

// bytes.MinRead = 512
func ReadAll(r io.Reader) ([]byte, error) {
	return readAll(r, bytes.MinRead)
}

可以看到 ioutil.ReadAll 每次都會分配初始化一個大小為 bytes.MinRead 的 buffer ,bytes.MinRead 在 Golang 里是一個常量,值為 512 。就是說每次調(diào)用 ioutil.ReadAll 都先會分配一塊大小為 512 字節(jié)的內(nèi)存。
接下來看一下ReadFrom函數(shù)的實(shí)現(xiàn):

func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
	b.lastRead = opInvalid
	// If buffer is empty, reset to recover space.
	if b.off >= len(b.buf) {
		b.Truncate(0)
	}
	for {
		if free := cap(b.buf) - len(b.buf); free < MinRead {
			// not enough space at end
			newBuf := b.buf
			if b.off+free < MinRead {
				// not enough space using beginning of buffer;
				// double buffer capacity
				newBuf = makeSlice(2*cap(b.buf) + MinRead)
			}
			copy(newBuf, b.buf[b.off:])
			b.buf = newBuf[:len(b.buf)-b.off]
			b.off = 0
		}
		m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
		b.buf = b.buf[0 : len(b.buf)+m]
		n += int64(m)
		if e == io.EOF {
			break
		}
		if e != nil {
			return n, e
		}
	}
	return n, nil // err is EOF, so return nil explicitly
}

ReadFrom函數(shù)主要作用就是從 io.Reader 里讀取的數(shù)據(jù)放入 buffer 中,如果 buffer 空間不夠,就按照每次 2x + MinRead 的算法遞增,這里 MinRead 的大小也是 512 Bytes 。
項(xiàng)目讀取的音頻文件一般很大,buffer不夠用,會一直調(diào)用makeSlice擴(kuò)容,消耗大量內(nèi)存,但是僅僅這樣,只是程序執(zhí)行時消耗了比較多的內(nèi)存,并未有內(nèi)存泄露的情況,那服務(wù)器又是如何內(nèi)存不足的呢?這就不得不扯到 Golang 的 GC 機(jī)制。

GC算法的觸發(fā)時機(jī)

golang的GC算法為三色算法,按理說會回收臨時變量,但是觸發(fā)GC的時機(jī)導(dǎo)致了這個問題:

  • 已分配的 Heap 到達(dá)某個閾值,會觸發(fā) GC, 該閾值由上一次 GC 時的 HeapAlloc 和 GCPercent 共同決定

  • 每 2 分鐘會觸發(fā)一次強(qiáng)制的 GC,將未 mark 的對象釋放,但并不還給 OS

  • 每 5 分鐘會掃描一個 Heap, 對于一直沒有被訪問的 Heap,歸還給 OS

ioutil.ReadAll會將全部的數(shù)據(jù)加載到內(nèi)存,一個大請求會多次調(diào)用makeSlice 分配很多內(nèi)存空間,并發(fā)的時候,會在很短時間內(nèi)占用大量的系統(tǒng)內(nèi)存,然后將 GC 閾值增加到一個很高的值,這個時候要 GC 就只有等 2 分鐘一次的強(qiáng)制 GC。這樣內(nèi)存中的數(shù)據(jù)無法及時GC,同時閾值還在不停的升高,導(dǎo)致GC的效率越來越低,最終導(dǎo)致緩慢的內(nèi)存泄漏。

解決方法

//req.AduioPack,err=ioutil.ReadAll(c.Resquest.Body)

buffer:=bytes.NewBuffer(make[]byte,0,6400)
_,err:=io.Copy(buffer,c.Resquest.Body)
temp:=buffer.Bytes()
req.AduioPack=temp

不是一次性把文件讀入內(nèi)存,而是申請固定的內(nèi)存大小。

到此,關(guān)于“go pprof如何使用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

網(wǎng)站標(biāo)題:gopprof如何使用
URL地址:http://chinadenli.net/article44/ppdhee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、全網(wǎng)營銷推廣網(wǎng)站制作、標(biāo)簽優(yōu)化自適應(yīng)網(wǎng)站微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計(jì)公司
日本加勒比不卡二三四区| 视频一区二区黄色线观看| 日韩亚洲激情在线观看| 久久99青青精品免费观看| 我要看日本黄色小视频| 亚洲欧洲一区二区中文字幕| 亚洲欧美黑人一区二区| 日本女优一区二区三区免费| 国内精品美女福利av在线| 日本在线不卡高清欧美 | 日韩特级黄片免费在线观看| 91精品日本在线视频| 成年男女午夜久久久精品| 国产欧美日韩精品自拍| 国产精品午夜小视频观看| 亚洲一区二区三区免费的视频| 久久国产人妻一区二区免费| 最近中文字幕高清中文字幕无| 欧美午夜国产在线观看| 亚洲av日韩av高潮无打码| 偷拍偷窥女厕一区二区视频| 日韩精品中文字幕亚洲| 欧美日韩国内一区二区| 一区二区欧美另类稀缺| 日韩精品综合免费视频| 欧美午夜色视频国产精品| 操白丝女孩在线观看免费高清| 国产三级欧美三级日韩三级| 五月婷婷欧美中文字幕| 亚洲国产成人精品一区刚刚| 日韩欧美三级中文字幕| 亚洲中文字幕视频在线观看| 熟女白浆精品一区二区| 亚洲色图欧美另类人妻| 亚洲妇女黄色三级视频| 日韩欧美综合在线播放| 国产欧美日韩综合精品二区| 激情中文字幕在线观看| 国产又粗又猛又爽色噜噜| 男人操女人下面国产剧情| 亚洲国产一级片在线观看 |