A high-performance memory allocator for Go that reduces garbage collection (GC) overhead by managing object lifetimes explicitly.
- Reduces GC Pressure: Allocates objects in contiguous chunks, minimizing GC scans.
- Zero-Allocation APIs: Methods like
Malloc,New, andNewSliceavoid heap allocations. - Thread Safety: Optional spinlock-based synchronization.
- Customizable: Configure chunk sizes, memory sources, and pooling behavior.
- Rich Utilities: Includes type-safe vectors (
Vector[T]) and deep-copy helpers.
- High-throughput services with frequent small object allocations.
- Long-lived objects that benefit from bulk deallocation.
- Latency-sensitive applications needing predictable GC behavior.
go get github.com/limpo1989/arenapackage main
import (
"fmt"
"github.com/limpo1989/arena"
)
func main() {
ar := arena.NewArena()
defer ar.Reset()
// Allocate primitives
num := arena.New[int](ar)
*num = 42
fmt.Println("print num:", *num)
// Allocate slices
slice := arena.NewSlice[string](ar, 0, 10)
slice = arena.Append(ar, slice, "hello", "world")
fmt.Println("print slice:", slice)
// Use vectors
vec := arena.NewVector[int](ar, 8)
vec.Append(1, 2, 3)
fmt.Println("print vec:", vec.At(0), vec.At(1), vec.At(2))
}
// Output:
// print num: 42
// print slice: [hello world]
// print vec: 1 2 3Arena reduces GC pauses by:
- Bulk Allocation: Objects are grouped in chunks, decreasing GC scan count.
- Lifetime Control: Allocations are freed together via Reset().
- Reduced Fragmentation: Chunk reuse minimizes heap fragmentation.
TestHeapLargeObjects Heap GC took time: 224.9326ms, living objects: 25001072
TestArenaLargeObjects Arena GC took time: 14.0116ms, living objects: 16819
- Manual Management: You must call Free or Reset to reclaim memory.
- No GC Integration: Arena-allocated objects are ignored by Go's GC.
- Pointer Safety: Mixing Arena and heap pointers may cause leaks/errors.
- Unsupported Types: map, channel, func
Mixing Arena and heap pointers
func main() {
ar := NewArena()
defer ar.Reset()
type subject struct {
id int32
age *int32
}
p := New[subject](ar)
p.age = new(int32) // Bad:store heap pointer
*p.age = 100
// You can setting a finalizer, it is possible to observe that the heap memory pointer will be reclaimed before the Arena ends
//
runtime.SetFinalizer(p.age, func (p *int32) {
fmt.Println("subject.age released")
})
runtime.GC()
fmt.Println("gc finished 1")
runtime.GC()
fmt.Println("gc finished 2")
// Undefined access, in fact, this part of memory has already been reclaimed by GC.
// Although it might be possible to access it here, it will result in undefined behavior
//
*p.age = 99 // Undefined access
}The arena is released under version 2.0 of the Apache License.