近日,Go 語言社群正在討論名為「arena」的新提案。
據介紹,arena 是一種從連續的記憶體區域分配一組記憶體物件的方法,其優點是從 arena 分配物件通常比一般記憶體分配更有效,更重要的是,arena 中的物件可以以最少的記憶體管理或垃圾回收開銷一次釋放所有內容。
arena 通常不會在具備垃圾回收的程式語言中實現,因為它們用於顯式釋放 arena 記憶體的操作並不安全,所以不符合垃圾回收語義。
但是,此提案的實現使用了動態檢查來確保 arena 操作是安全的。如果 arena 操作不安全,程式將在任何不正確的行為發生之前終止。
目前 Go 團隊已在Google 內部使用了arena,結果顯示 arena為許多大型應用程式節省了高達 15% 的 CPU 和記憶體使用量,這主要是由於垃圾回收CPU 時間和堆記憶體使用量的減少。
提案介紹
Go 團隊試圖在Go 標準庫中新增一個新的 arena 包。arena 包將分配任意數量的 arena,可以從 arena 的記憶體中分配任意型別的物件,並且 arena 會根據需要自動增長大小。
當一個 arena 中的所有物件不再使用時,可以顯式釋放該 arena 以有效地回收其記憶體,而無需進行一般的垃圾回收操作。Go 團隊要求此實現提供安全檢查,如果 arena操作不安全,程式將在任何不正確的行為發生之前終止。為了獲得最大的靈活性,API 能夠分配任何型別的物件和切片,包括可以在執行時通過反射生成的型別。
提案 API
package arena
type Arena struct {
// contains filtered or unexported fields
}
// New allocates a new arena.
func New() *Arena
// Free frees the arena (and all objects allocated from the arena) so that
// memory backing the arena can be reused fairly quickly without garbage
// collection overhead. Applications must not call any method on this
// arena after it has been freed.
func (a *Arena) Free()
// New allocates an object from arena a. If the concrete type of objPtr is
// a pointer to a pointer to type T (**T), New allocates an object of type
// T and stores a pointer to the object in *objPtr. The object must not
// be accessed after arena a is freed.
func (a *Arena) New(objPtr interface{})
// NewSlice allocates a slice from arena a. If the concrete type of slicePtr
// is *[]T, NewSlice creates a slice of element type T with the specified
// capacity whose backing store is from the arena a and stores it in
// *slicePtr. The length of the slice is set to the capacity. The slice must
// not be accessed after arena a is freed.
func (a *Arena) NewSlice(slicePtr interface{}, cap int)
用法示例:
import (
“arena”
…
)
type T struct {
val int
}
func main() {
a := arena.New()
var ptrT *T
a.New(&ptrT)
ptrT.val = 1
var sliceT []T
a.NewSlice(&sliceT, 100)
sliceT[99] .val = 4
a.Free()
}