一文搞懂Golang中的內(nèi)存逃逸
前言
我們都知道go語言中內(nèi)存管理工作都是由Go在底層完成的,這樣我們可以不用過多的關(guān)注底層的內(nèi)存問題,有更多的精力去關(guān)注業(yè)務(wù)邏輯, 但掌握內(nèi)存的管理,理解內(nèi)存分配機制,可以讓你寫出更高效的代碼,本文主要總結(jié)一下 Golang內(nèi)存逃逸分析,需要的朋友可以參考以下內(nèi)容,希望對大家有幫助。
什么是內(nèi)存逃逸
在了解什么是內(nèi)存逃逸之前,我們先來了解兩個概念,棧內(nèi)存和堆內(nèi)存。
堆內(nèi)存(Heap):一般來講是人為手動進行管理,手動申請、分配、釋放。一般硬件內(nèi)存有多大堆內(nèi)存就有多大。適合不可預(yù)知大小的內(nèi)存分配,分配速度較慢,而且會形成內(nèi)存碎片。
棧內(nèi)存(Stack):是一種擁有特殊規(guī)則的線性表數(shù)據(jù)結(jié)構(gòu)。由編譯器進行管理,自動申請、分配、釋放。大小一般是固定的。
通過上面我們可以看出堆分配昂貴,棧分配廉價,在go中所有內(nèi)存優(yōu)先棧分配,那么,Go 編譯器怎么知道某個變量需要分配在棧上,還是堆上呢?
逃逸分析是用于堆和棧分配進行選擇,通過在編譯時期做gc,編譯器追蹤變量在代碼塊的作用域,判斷變量在整個運行周期是否在運行時完全可知,通過校驗可以在棧上分配;否則逃逸到堆上;逃逸分析由編譯器完成,作用于編譯階段。
查看對象是否發(fā)生逃逸
Go 語言工具鏈提供了查看對象是否逃逸的方法,我們在執(zhí)行 go build 時,配合使用參數(shù) -gcflags 開啟編譯器支持的額外功能,例如:
go build -gcflags '-m -l' main.go
-m
會打印出逃逸分析的優(yōu)化策略,實際上最多總共可以用 4 個 -m
,但是信息量較大,一般用 1 個就可以了
-l
會禁用函數(shù)內(nèi)聯(lián),在這里禁用掉 inline
能更好的觀察逃逸情況,減少干擾。
除了使用編譯參數(shù)之外,我們還可以使用一種更底層的,更硬核,也更準確的方式來判斷一個對象是否逃逸,那就是: 通過反編譯命令查看
go tool compile -S main.go
示例:
func main() { sum(1, 2) } func sum(a, b int) *int { res := a + b return &res }
結(jié)果如下,第7行變量 res 逃逸到了堆上
內(nèi)存逃逸分析的意義
通過逃逸分析,可以盡量把那些不需要分配到堆上的變量直接分配到棧上,堆上的變量少了,會減輕分配堆內(nèi)存的開銷,同時也會減少GC的壓力,提高程序的運行速度。
怎么避免內(nèi)存逃逸
盡量減少外部指針引用,必要的時候可以使用值傳遞;
對于自己定義的數(shù)據(jù)大小,有一個基本的預(yù)判,盡量不要出現(xiàn)??臻g溢出的情況;
Golang中的接口類型的方法調(diào)用是動態(tài)調(diào)度,如果對于性能要求比較高且訪問頻次比較高的函數(shù)調(diào)用,應(yīng)該盡量避免使用接口類型;
盡量不要寫閉包函數(shù),可讀性差且發(fā)生逃逸。
小結(jié)
本文主要介紹了 Go 語言逃逸分析,它可以幫助我們合理分配對象的內(nèi)存空間。
我們知道分配到堆內(nèi)存空間的對象,會導(dǎo)致 Go 執(zhí)行垃圾回收,而垃圾回收會占用系統(tǒng)資源,降低應(yīng)用程序本身可使用的系統(tǒng)資源。
所以,我們在實際項目開發(fā)中,可以借助 Go 工具鏈分析對象是否會發(fā)生逃逸,盡量避免一些不必要的對象逃逸。
到此這篇關(guān)于一文搞懂Golang中的內(nèi)存逃逸的文章就介紹到這了,更多相關(guān)Go內(nèi)存逃逸內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang通道阻塞情況與通道無阻塞實現(xiàn)小結(jié)
本文主要介紹了Golang通道阻塞情況與通道無阻塞實現(xiàn)小結(jié),詳細解析了通道的類型、操作方法以及垃圾回收機制,從基礎(chǔ)概念到高級應(yīng)用,具有一定的參考價值,感興趣的可以了解一下2024-03-03Go語言調(diào)用DeepSeek?API實現(xiàn)流式輸出和對話
DeepSeek是一個強大的AI模型服務(wù)平臺,本文將詳細介紹如何使用Go語言調(diào)用DeepSeek?API實現(xiàn)流式輸出和對話功能,感興趣的小伙伴可以了解一下2025-02-02golang gin ShouldBind的介紹和使用示例詳解
在 Go 語言的 Gin 框架中,ShouldBind 是用于將請求中的數(shù)據(jù)綁定到結(jié)構(gòu)體的一個方法,它簡化了從請求中提取參數(shù)的過程,支持多種數(shù)據(jù)格式,下面給大家分享golang gin ShouldBind的介紹和使用示例,感興趣的朋友一起看看吧2024-10-10Go實現(xiàn)List、Set、Stack、Deque等數(shù)據(jù)結(jié)構(gòu)的操作方法
Go語言團隊的一個核心目標是保持語言的簡單性,他們認為,如果一個功能可以用簡單的組合來實現(xiàn),那就沒有必要把它放進標準庫里,本文給大家介紹Go實現(xiàn)List、Set、Stack、Deque等數(shù)據(jù)結(jié)構(gòu)的操作方法,感興趣的朋友跟隨小編一起看看吧2024-12-12