GoLang內(nèi)存泄漏原因排查詳解
背景
Go 語言中有對應(yīng)的Go 內(nèi)存回收機制,在Go采用 并發(fā)三色標(biāo)記清除 算法, 但是由于實際的過程中 發(fā)現(xiàn)會有一些內(nèi)存泄漏的常見,內(nèi)存泄漏 分為: 臨時性 和 永久性內(nèi)存泄漏。
初步排查過程中: 發(fā)現(xiàn)Linux使用top 發(fā)現(xiàn)內(nèi)存隨著時間會持續(xù)的增加沒有穩(wěn)定在一個合理值中。
在使用 pprof ,BBC 等 Go的內(nèi)存泄漏工具進行排查
臨時性內(nèi)存泄漏
指的釋放內(nèi)存 不及時,對應(yīng)的內(nèi)存在更晚時候釋放,這類問題主要是 string,slice 和底層的Buffer 錯誤共享,或者defer 函數(shù)資源沒有及時的釋放。
數(shù)組不正常使用導(dǎo)致內(nèi)存泄漏
數(shù)組作為形參 遵守的是 值拷貝,如果函數(shù)調(diào)用次數(shù)很多并且數(shù)組過大,導(dǎo)致 內(nèi)存使用激增
func countTragetBigNum(nums [1000000]int, target int) int { num := 0 for i :=0; i< len(nums) && nums[i] ==target ; i++ { num += 1 } return num } # 在短時間內(nèi) 創(chuàng)建100萬數(shù)組 內(nèi)存是8M,短時間內(nèi)調(diào)用 100 次,并且作為是形參 在Go進行是 值Copy ,800M, 所以在時間過程中:
大數(shù)組在形參的場景下,通常使用的是切片方式?;蛘呤褂弥羔樳M行傳遞,避免在短時間內(nèi)內(nèi)存激增
goroutine 沒有及時釋放
一個 goroutine 創(chuàng)建 2KB
1. 互斥鎖沒有釋放 func mutexTest() { mutex := sync.Mutex{} for i := 0; i < 10; i++ { go func () { mutex.Lock() fmt.Printf("%d goroutine get mutex", i) time.Sleep(100 * time.Microsecond) }() } } 2. 死鎖情形 3. 空channel --聲明空channel但是沒有初始化 導(dǎo)致讀寫被阻塞 func channelTest(){ // 聲明空 channel且不初始化導(dǎo)致阻塞 var c chan int // 向通道中寫數(shù)據(jù) go func() { c <- 1 fmt.Printf("g1 send message") }() // 從通道中讀數(shù)據(jù) go func(){ <- c fmt.Printf("g2 receive message") }() } 4. 能進不能出, 能出不能進 (寫和讀 通道量不一致) 導(dǎo)致大量的協(xié)程被阻塞 func channelTest() { // 聲明空 channel且不初始化導(dǎo)致阻塞 var c chan int // 10 個向通道中寫數(shù)據(jù),導(dǎo)致 寫大于讀量 // 10個通道讀數(shù)據(jù),1個通道寫數(shù)據(jù)也是一樣的 for i := 0; i < 10; i++ { go func() { c <- i fmt.Printf("g1 send message") }() } // 從通道中讀數(shù)據(jù) go func() { <-c fmt.Printf("g2 receive message") }() } 5. Time 定時器使用 定時器沒有 手動Stop 會一直占有內(nèi)存 func tickerTest() { ticker := time.NewTicker(time.Second * 20) go func() { for t := range ticker.C { fmt.Printf("ticker trigger") } }() time.Sleep(time.Second * 20) ticker.Stop() }
通道理解
通道 channel 屬于Go語言中首次提出的 運用 goroutine 的進行數(shù)據(jù)交換的 容器;
- 緩沖通道屬于一個元素隊列, 有先入先出原則, 屬于線程安全
- 如果通道滿了, 發(fā)送goroutine 會阻塞直到 read goroutine 進行接收操作
- 如果通道是空的, 執(zhí)行接收goroutine 阻塞直到 write goroutine 在通道上發(fā)送數(shù)據(jù);
- 通道既不滿也不空,所以通道的緩沖區(qū)將發(fā)送和接收 goroutine 進行解耦操作
如果程序直到 緩沖區(qū)的容量, 可以調(diào)用 內(nèi)置的 cap函數(shù) cap(ch) -- 緩沖區(qū)容量
len(ch) -- 緩沖區(qū)內(nèi) 元素個數(shù)
goroutine 泄漏: 使用一個無緩沖通道,兩個慢的 goroutine 卡住,發(fā)送的響應(yīng)的結(jié)果沒有其他的goroutine 接收 這個情況屬于 goroutine 泄漏;
如果讀速度比較快,緩沖區(qū)存是沒有意義的
到此這篇關(guān)于GoLang內(nèi)存泄漏原因排查詳解的文章就介紹到這了,更多相關(guān)Go內(nèi)存泄漏內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
掌握GoLang Fiber路由和中間件技術(shù)進行高效Web開發(fā)
這篇文章主要為大家介紹了GoLang Fiber路由和中間件進行高效Web開發(fā),本文將深入探討 Fiber 中的路由細節(jié),學(xué)習(xí)如何創(chuàng)建和處理路由,深入了解使用路由參數(shù)的動態(tài)路由,并掌握在 Fiber 應(yīng)用程序中實現(xiàn)中間件的藝術(shù)2024-01-01golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法
這篇文章主要介紹了golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12Golang中文字符串截取函數(shù)實現(xiàn)原理
在golang中可以通過切片截取一個數(shù)組或字符串,但是當(dāng)截取的字符串是中文時,可能會出現(xiàn)問題,下面我們來自定義個函數(shù)解決Golang中文字符串截取問題2018-03-03解決golang sync.Wait()不執(zhí)行的問題
這篇文章主要介紹了解決golang sync.Wait()不執(zhí)行的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12一個簡單的Golang實現(xiàn)的HTTP Proxy方法
今天小編就為大家分享一篇一個簡單的Golang實現(xiàn)的HTTP Proxy方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08