arena

package module
v0.0.0-...-e551e85 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 3, 2025 License: MIT Imports: 3 Imported by: 0

README

Golang Arena Memory Allocator

A high-performance Go library providing arena-based memory allocation for any type. This library significantly reduces garbage collection pressure and allocation costs by pre-allocating memory in chunks and reusing it efficiently. It can improve performance 3 to 5x for use cases that require allocation of many small objects like binary tree or linked list.

Features & Performance Benefits

  • Generic Support: Works with any Go type using generics
  • Concurrent Safe: Thread-safe Arena for multi-goroutine scenarios
  • Single-threaded Optimized: LocalArena for better performance in single-goroutine use cases
  • Lock-free Algorithm: Uses atomic operations without mutexes for optimal performance
  • Reduced GC Pressure: Pre-allocates memory in large chunks instead of individual allocations, minimizing garbage collection overhead
  • Zero-copy Design: Returns pointers to pre-allocated memory, reusing memory within chunks to minimize heap pressure
  • Enhanced Performance: Avoids frequent small allocations that cost more GC cycles and improves CPU cache locality by allocating related objects contiguously in memory

Trade-off: If a single object from an arena chunk remains alive, the entire chunk will be kept in memory until that reference is released. This is the cost of the performance that you gain. A wiseman once said with great power comes great irresponsibility.

Installation

go get github.com/fereidani/arena

Usage

Concurrent Arena

For multi-goroutine scenarios:

package main

import (
	"fmt"
	"sync"

	"github.com/fereidani/arena"
)

type Node struct {
	Value int
	Left  *Node
	Right *Node
}

func buildTree(a *arena.Arena[Node], depth int) *Node {
	if depth > 25 {
		return nil
	}
	node := a.Get() // *Node
	node.Value = depth
	node.Left = buildTree(a, depth+1)
	node.Right = buildTree(a, depth+1)
	return node
}

func main() {
	// Create arena with chunk size of 1024
	a := arena.NewArena[Node](1024)

	var wg sync.WaitGroup

	// Launch multiple goroutines to build left and right branches concurrently
	wg.Add(2)
	root := a.Get()
	root.Value = 1

	go func() {
		defer wg.Done()
		root.Left = buildTree(a, 2)
	}()

	go func() {
		defer wg.Done()
		root.Right = buildTree(a, 2)
	}()

	wg.Wait()

	fmt.Println(root.Value)
}
Local Arena

For single-goroutine scenarios (better performance):

package main

import "github.com/fereidani/arena"

type Node struct {
    Value int
    Left  *Node
    Right *Node
}

func buildTree(a *arena.LocalArena[Node], depth int) *Node {
    if depth > 25 {
        return nil
    }
    node := a.Get() // *Node
    node.Value = depth
    node.Left = buildTree(a, depth + 1)
    node.Right = buildTree(a, depth + 1)
    return node
}

func main() {
    // Create local arena with chunk size of 500
    a := arena.NewLocalArena[Node](1024)

    // Build a simple binary tree
    root := buildTree(a, 1)
}

API Reference

Arena[T]

Thread-safe arena allocator.

  • NewArena[T](chunkSize int) *Arena[T]: Creates a new concurrent arena
  • Get() *T: Returns a pointer to a new allocated item
LocalArena[T]

Single-threaded arena allocator with better performance.

  • NewLocalArena[T](chunkSize int) *LocalArena[T]: Creates a new local arena
  • Get() *T: Returns a pointer to a new allocated item

Memory Management

  • Chunks are allocated with the specified size (default: 1024)
  • When a chunk is exhausted, a new chunk of the same size is allocated
  • Memory is not automatically freed - chunks remain allocated until all references are released
  • Choose chunk sizes based on your allocation patterns and memory constraints

License

MIT License

arena

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Arena

type Arena[T any] struct {
	// contains filtered or unexported fields
}

Arena provides arena memory allocator for a specific type

func NewArena

func NewArena[T any](chunkSize int) *Arena[T]

NewArena creates a new Arena with the specified chunk size. If chunkSize is zero or negative, it defaults to 1024. The arena pre-allocates memory for chunkSize elements of type T.

Note: Arena is safe for concurrent use. Multiple goroutines can safely call Get() on the same Arena instance simultaneously. If concurrency is not required, consider using NewLocalArena instead as it provides better performance for single goroutine use cases.

func (*Arena[T]) Get

func (a *Arena[T]) Get() *T

Get allocates and returns a pointer to a new item of type T

type LocalArena

type LocalArena[T any] struct {
	// contains filtered or unexported fields
}

func NewLocalArena

func NewLocalArena[T any](chunkSize int) *LocalArena[T]

NewLocalArena creates a new LocalArena with the specified chunk size. If chunkSize is zero or negative, it defaults to 1024. The arena pre-allocates memory for chunkSize elements of type T.

Note: LocalArena is not safe for concurrent use. It is designed for single goroutine use cases where it provides better performance than the thread-safe Arena allocator.

func (*LocalArena[T]) Get

func (a *LocalArena[T]) Get() *T

Get returns a pointer to the next available element in the arena. If the arena has available elements, it advances the internal index and returns a pointer to the current element. If the arena is full, it allocates a new slice with the same length, resets the index, and returns a pointer to the first element of the new slice.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL