Go 語言新提案「arena」:優化記憶體

2022-03-01 09:00:14

Go 語言社群正在討論名為的新提案。

根據提案的介紹,「Go arena」用於優化記憶體分配。arena 是一種從連續的記憶體區域分配一組記憶體物件的方法,其優點是從 arena 分配物件通常比一般記憶體分配更有效。更重要的是,arena 中的物件能夠用最少的記憶體管理垃圾回收開銷一次釋放所有內容。

通常來說,arena 不會在具備垃圾回收的程式語言中實現,因為它們用於顯式釋放 arena 記憶體的操作不安全,所以不符合垃圾回收語意。不過此提案的實現使用了動態檢查來確保 arena 操作是安全的。此外還保證,如果 arena 操作不安全,程式將在任何不正確的行為發生之前終止。目前 Go 團隊已在 Google 內部實現並使用了 arena,結果顯示其為許多大型應用程式節省了高達 15% 的 CPU 和記憶體使用量,這主要是由於垃圾回收 CPU 時間和堆記憶體使用量的減少。

提案簡介

在 Go 標準庫中增加一個新的arena包,arena包可用於分配任意數量的 arena,可以從 arena 的記憶體中分配任意型別的物件,並且 arena 會根據需要自動增長大小。當一個 arena 中的所有物件不再使用時,可以顯式釋放該 arena 以有效地回收其記憶體,而無需進行常見的垃圾回收操作。我們要求此實現提供安全檢查,如果 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)

arena 用法範例:

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()
}
展開閱讀全文