Go 內(nèi)存分配管理
一、問題引入
現(xiàn)象:在實(shí)際工作項(xiàng)目中,golang項(xiàng)目經(jīng)常內(nèi)存報(bào)警,現(xiàn)象為在流量增大,或傳入很大文件的情況下算法worker內(nèi)存降低到一定限度之后(100Mb左右),過一段時(shí)間才能內(nèi)存才能自動(dòng)恢復(fù)。
- Go內(nèi)存管理機(jī)制,Go自己本身會(huì)管理內(nèi)存,釋放的內(nèi)存不會(huì)立即歸還給操作系統(tǒng),在一定時(shí)間之后才會(huì)歸還給操作系統(tǒng),過早的釋放內(nèi)存歸還給操作系統(tǒng)會(huì)降低性能。
- 內(nèi)存泄漏,Go調(diào)用CGO算法模塊時(shí),導(dǎo)致了內(nèi)存泄漏
- 進(jìn)程占用的內(nèi)存過大導(dǎo)致進(jìn)程掛掉,并釋放了內(nèi)存,
supervisor
自動(dòng)重啟了進(jìn)程,內(nèi)存曲線恢復(fù)正常
二、幾個(gè)基本概念
1.RSS,VSS解釋
對(duì)于RAM
內(nèi)存的使用,實(shí)際是os kernel
來控制的。
RSS(Resident Set Size)
表示該進(jìn)程分配的占用RAM的內(nèi)存大小,不包括交互分區(qū)內(nèi)存,包括共享庫占用的內(nèi)存,棧內(nèi)存,堆內(nèi)存VSZ(Virtual Memory Size)
表示該進(jìn)程分配的虛擬內(nèi)存大小,包括進(jìn)程可以訪問的所有內(nèi)存,包括交換分區(qū),共享內(nèi)存
舉例說明RSS,VSS:
如果一個(gè)進(jìn)程,程序的大小有 500K,鏈接的共享庫大小有 2500K,堆棧內(nèi)存共有 200K,其中 100K 進(jìn)入了交換分區(qū)。進(jìn)程實(shí)際加載了共享庫中的 1000K 的內(nèi)容,以及自己程序的中的 400K 的內(nèi)容。請(qǐng)問 RSS 和 VSZ 應(yīng)是多少?RSS: 400K + 1000K + 100K = 1500K VSZ: 500K + 2500K + 200K = 3200K
三、Go內(nèi)存管理機(jī)制
1.Go runtime內(nèi)存延遲歸還
Go是一種高級(jí)語言,自帶GC。內(nèi)存的分配和回收都是自動(dòng)的被垃圾回收器所執(zhí)行,當(dāng)某個(gè)對(duì)象內(nèi)存變成不可達(dá)狀態(tài)時(shí)(unreachable
)。垃圾回收器則將其回收。
Go中空閑的內(nèi)存,并不意味著立即歸還給操作系統(tǒng)??臻e的內(nèi)存可以被重新利用。因此Go語言中,即使某些對(duì)象被釋放了,操作系統(tǒng)的內(nèi)存使用并沒有下降。這是因?yàn)镚o的內(nèi)存管理器,將其標(biāo)為free,并可以重新利用。
Go runtime
不會(huì)立刻歸還內(nèi)存給操作系統(tǒng),內(nèi)存在大約5分鐘左右沒有被使用時(shí),才會(huì)歸還給操作系統(tǒng)。
例如:在處理Http請(qǐng)求時(shí)讀取HttpBody
到Bytes.Buffer
中,處理完HttpBody的內(nèi)容之后,并不會(huì)立刻釋放內(nèi)存給OS,而是將這些內(nèi)存對(duì)下一個(gè)Http請(qǐng)求進(jìn)行內(nèi)存的復(fù)用。
編寫如下:簡(jiǎn)單的http服務(wù),并使用ab進(jìn)行壓測(cè)可以驗(yàn)證Go gc的延遲歸還內(nèi)存給操作系統(tǒng):
func main() { ? ? ? http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { ? ? ? ? ? fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) ? ? ? }) ? ? ? http.ListenAndServe(":8010", nil) ? ? ? fmt.Println("hello") ? } ?
初始:
$ ps -p 563 -v ? ? PID TTY ? ? ?STAT ? TIME ?MAJFL ? TRS ? DRS ? RSS %MEM COMMAND ? ? 563 pts/19 ? SNl ? ?0:27 ? ? ?0 ?2100 359203 ?3480 ?0.1 ./http ?
壓測(cè)后:
ab -n 1000000 -c 1000 http://10.104.7.46:8010/bar
$ ps -p 563 -v ? ? PID TTY ? ? ?STAT ? TIME ?MAJFL ? TRS ? DRS ? RSS %MEM COMMAND ? ? 563 pts/19 ? SNl ? ?0:27 ? ? ?0 ?2100 359203 12908 ?0.1 ./http ?
5min后:
$ ps -p 563 -v ? ? PID TTY ? ? ?STAT ? TIME ?MAJFL ? TRS ? DRS ? RSS %MEM COMMAND ? ? 563 pts/19 ? SNl ? ?0:27 ? ? ?0 ?2100 359203 4816 ?0.0 ./http ?
可以看到RSS由3480到12908在到4816,結(jié)合free -m可以看到內(nèi)存一樣的變化,因此驗(yàn)證了golang的內(nèi)存管理的延遲歸還特性。
2.強(qiáng)制歸還內(nèi)存
debug.FreeOSMemory()
該函數(shù)強(qiáng)制盡可能多的將內(nèi)存歸還給操作系統(tǒng)。不推薦手動(dòng)調(diào)用釋放內(nèi)存,
FreeOSMemory
的操作在后臺(tái)進(jìn)程runtime
來負(fù)責(zé)執(zhí)行,定期歸還內(nèi)存給操作系統(tǒng)。
到此這篇關(guān)于Go 內(nèi)存分配管理的文章就介紹到這了,更多相關(guān)Go 內(nèi)存管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理分析
這篇文章主要介紹了Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理,HTTP服務(wù)的超時(shí)控制是保障服務(wù)高可用性的重要措施之一,由于HTTP服務(wù)可能會(huì)遇到網(wǎng)絡(luò)延遲,資源瓶頸等問題,因此需要對(duì)請(qǐng)求進(jìn)行超時(shí)控制,以避免服務(wù)雪崩等問題,需要的朋友可以參考下2023-05-05go語言實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的方法
這篇文章主要介紹了go語言實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的方法,涉及Go語言http操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02go語言的panic和recover函數(shù)用法實(shí)例
今天小編就為大家分享一篇關(guān)于go語言的panic和recover函數(shù)用法實(shí)例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-04-04Go interface接口聲明實(shí)現(xiàn)及作用詳解
這篇文章主要為大家介紹了Go interface接口聲明實(shí)現(xiàn)及作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Golang打包go項(xiàng)目部署到linux服務(wù)器正確方法
這篇文章主要給大家介紹了關(guān)于Golang打包go項(xiàng)目部署到linux服務(wù)器的正確方法,Go?是一個(gè)開源的編程語言,它能讓構(gòu)造簡(jiǎn)單、可靠且高效的軟件變得容易,具有簡(jiǎn)潔、快速、安全,并行、有趣、開源,內(nèi)存管理、v數(shù)組安全、編譯迅速的特征,需要的朋友可以參考下2023-10-10