Go1.20 arena 能手動(dòng)管理內(nèi)存了,怎么用?
大家好,我是煎魚。
最近 Go1.20 中的手動(dòng)管理內(nèi)存受到了很多人的關(guān)注。眾所周知,Go 是一門帶垃圾回收(GC)的編程語(yǔ)言,可以進(jìn)行自動(dòng)的內(nèi)存申請(qǐng)、釋放等內(nèi)存操作。
帶 GC 能簡(jiǎn)化編程時(shí)的心智成本,也保證了內(nèi)存的安全。我們說 “一般”,也就是有例外。人們說六個(gè),一般都有七個(gè)。
Go 的例外就出現(xiàn)了。
Go1.20 arena
新版本 Go1.20,基于 Google 自身的需求,快速通過了實(shí)踐,正式支持了 arena,能夠?qū)崿F(xiàn)手動(dòng)的內(nèi)存管理(當(dāng)前是實(shí)驗(yàn)性特性)。
現(xiàn)在可以通過 GOEXPERIMENT=arenas 環(huán)境變量啟用:
該特性可以讓程序員手動(dòng)的從一個(gè)連續(xù)的內(nèi)存區(qū)域申請(qǐng)、分配一組內(nèi)存對(duì)象,也可以一次性的釋放。
重點(diǎn)是可以手動(dòng)管理內(nèi)存。
提供的 arena API
- NewArena:創(chuàng)建一個(gè)新的 arena 內(nèi)存空間。
- Free:釋放 arena 及其關(guān)聯(lián)對(duì)象。
- New:基于 arena,創(chuàng)建新對(duì)象。
- MakeSlice:基于 arena,創(chuàng)建新切片。
- Clone:克隆一個(gè) arena 的對(duì)象,并移動(dòng)到內(nèi)存堆上。
一些 arena 例子
以下案例和性能測(cè)試是基于 uptrace 在 Golang memory arenas [101 guide][1] 中分享的 arena 例子,本處進(jìn)行引用,我就不自創(chuàng)一份了。
很適合在初學(xué)時(shí)作為 Demo 使用,打算也留著自己下次用時(shí)結(jié)合文檔翻一番。
arena.NewArena
一起來快速入門。代碼如下:
arena.Clone
如果要單獨(dú)使用某個(gè)申請(qǐng)出來的對(duì)象??梢越柚?Clone 方法進(jìn)行單獨(dú)處理。
如下代碼:
釋放了最早申請(qǐng)的 arena,Clone 方法在這里將會(huì)把 obj1 拷貝到新的內(nèi)存堆上,再賦值給 obj2。后續(xù)要單獨(dú)用 obj2 就可以繼續(xù)使用。
reflect.ArenaNew
也可以結(jié)合 arena 和 reflect 兩個(gè)標(biāo)準(zhǔn)庫(kù)來進(jìn)行使用。如下代碼:
arena.MakeSlice
該方法的常規(guī)用法:
如果需要申請(qǐng)一個(gè)新切片并追加元素:
需要注意的是,arena 目前不支持 map。但你可以通過泛型來實(shí)現(xiàn)類似的效果。
arena.String
原則上 arena 不支持 string。但是我們依然可以通過 unsafe.String 方法的騷操作來變相實(shí)現(xiàn)。
如下代碼:
在申請(qǐng)的 arena 釋放后,該對(duì)應(yīng)的 string 就無法使用了,需要特別注意。
性能表現(xiàn)
這個(gè)允許手工管理內(nèi)存的 arena 的特性是來源于內(nèi)部,提案也是一路綠燈通過。(懂得懂)。
自述已經(jīng)為 Google 許多應(yīng)用節(jié)省了高達(dá) 15% 的 CPU 和內(nèi)存使用量,主要原因是減少了垃圾收集 CPU 時(shí)間和堆內(nèi)存使用量。
經(jīng)過在 vmihailenco/golang-memory-arenas[2] 項(xiàng)目中實(shí)際的性能對(duì)比。
沒有用 arena:
使用了 arena:
使用了 arena 的代碼運(yùn)行速度更快,且使用的內(nèi)存更少。
總結(jié)
Go 的各位大大們?cè)谛阅軆?yōu)化中,不斷地試圖壓榨 Go 的潛力?,F(xiàn)在已經(jīng)到了手工管理內(nèi)存的階段了。
實(shí)際的測(cè)試結(jié)果來看,是有作用的。
有興趣的小伙伴可以在 Go1.20 起就開始試用。不過需要注意,該特性由于發(fā)現(xiàn)了嚴(yán)重的 API 問題(想把 arena 應(yīng)用到其他的標(biāo)準(zhǔn)庫(kù)中,但這是個(gè)大事件),社區(qū)還需要認(rèn)真思考后續(xù)的發(fā)展,現(xiàn)階段處于處于停滯狀態(tài)。
從這次提案來看,真的是,內(nèi)部需求一路猛如虎,直接沖上 master。外部需求就畏畏縮縮了。真雙標(biāo)?