memoryArena

package module
v1.10.38 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2025 License: MIT Imports: 6 Imported by: 0

README

Memory Arena Library for Golang

Go Report Card

Memory Arena Library is a Golang package that consolidates multiple related memory allocations into a single area. This design allows you to free all allocations at once, making memory management simpler and more efficient.

Features

  • Generic: works with any Go type (int, structs, pointers, etc.).
  • Grouped Memory Allocations: Manage related objects within a single arena, streamlining your memory organization.
  • Efficient Cleanup: Release all allocations in one swift operation, simplifying resource management.
  • Concurrency Support: Use with concurrent operations via a dedicated concurrent arena.
  • AtomicArena is a concurrent bump allocator for type-homogeneous objects in Go. It allows safe, lock-free allocations from multiple goroutines using atomic operations, making it well-suited for high-performance, multi-threaded environments.

Installation

Install the latest version with:

go get github.com/Raezil/memoryArena@latest

Usage Example

Below is an example demonstrating how to create a memory arena, allocate objects, and free them efficiently:

Using Memory Arena
package main

import (
	"fmt"
	"unsafe"

	. "github.com/Raezil/memoryArena"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	// Allocate enough space for 10 Person structs
	arena, err := NewMemoryArena[Person](10 * int(unsafe.Sizeof(Person{})))
	if err != nil {
		panic(err)
	}
	defer arena.Reset()

	p1, _ := arena.NewObject(Person{"Alice", 30})
	p2, _ := arena.NewObject(Person{"Bob", 25})

	fmt.Println(*p1, *p2)
}
Using Concurrent Arena
package main

import (
	"fmt"

	. "github.com/Raezil/memoryArena"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	arena, err := NewConcurrentArena[[]Person](100)
	if err != nil {
		return
	}
	obj, _ := arena.NewObject([]Person{Person{"Kamil", 27}, Person{"Lukasz", 28}})
	defer arena.Reset()
	fmt.Println(obj)

}
Using AtomicArena
package main

import (
	"fmt"
	"sync"

	. "github.com/Raezil/memoryArena"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	// Allocate 1KB buffer for Person allocations
	arena, err := NewAtomicArena[Person](1024)
	if err != nil {
		panic(err)
	}
	defer arena.Reset()

	var wg sync.WaitGroup
	for i, name := range []string{"Carol", "Dave", "Eve"} {
		wg.Add(1)
		go func(name string, age int) {
			defer wg.Done()
			p, _ := arena.NewObject(Person{name, age})
			fmt.Println(*p)
		}(name, i+20)
	}
	wg.Wait()
}

Testing & Benchmarks

Run all tests with race detection:

go test -v -race ./...

Run benchmarks:

go test -bench=. -benchmem

At 100 MB (100 000 000 B) allocations:

Strategy Latency (ns/op) Speedup vs new
Native new 19 861 997 1× (baseline)
AtomicArena.NewObject 7.149 ~2.8 × 10⁶
MemoryArena.NewObject 4.318 ~4.6 × 10⁶

AtomicArena reduces allocation time by ~2.8 million×.

MemoryArena reduces allocation time by ~4.6 million×.

Interpretation

  • Native new is optimized for very small allocations (< ~32 KB) using thread-local caches and bump-pointer fast paths.

  • Above the small-object threshold (~64 KB), the runtime falls back to slower heap allocations, causing large overhead for big buffers.

  • Arena allocation is O(1) time (constant time per allocation).

  • Arena allocators maintain constant, single-digit nanosecond performance regardless of buffer size, avoiding GC pressure.

Recommendations

  • Tiny objects (< 32 KB): use native new for simplicity and peak performance.

  • Large buffers (≥ 64 KB): use a bump-pointer arena (single-threaded or atomic) to keep allocations in the 4–7 ns range and bypass the GC.

📜 Contributing

Want to improve memoryArena? 🚀

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature-new)
  3. Commit your changes (git commit -m "Added feature")
  4. Push to your branch (git push origin feature-new)
  5. Submit a PR!

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrOutOfMemory     = errors.New("memory arena: out of memory")
	ErrArenaFull       = errors.New("memory arena: insufficient space")
	ErrInvalidSize     = errors.New("memory arena: size must be greater than 0")
	ErrNewSizeTooSmall = errors.New("memory arena: new size is smaller than current usage")
	ErrInvalidType     = errors.New("memory arena: invalid object type for this arena")
)

Functions

This section is empty.

Types

type Arena

type Arena[T any] interface {
	// Allocate reserves sz bytes (aligned for T) and returns a pointer to the start.
	Allocate(sz int) (unsafe.Pointer, error)
	// NewObject allocates space for one T, copies obj into it, and returns *T.
	NewObject(obj T) (*T, error)
	// Reset clears all allocations and resets the arena to empty state.
	Reset()
	// AppendSlice appends elems to an existing slice, growing in-arena if needed.
	AppendSlice(slice []T, elems ...T) ([]T, error)
	Offset() int
	Base() unsafe.Pointer
}

func NewAtomicArena added in v1.10.15

func NewAtomicArena[T any](size int) (Arena[T], error)

NewAtomicArena allocates an arena with at least `size` bytes of usable space. Returned addresses are naturally aligned for *T.

func NewConcurrentArena

func NewConcurrentArena[T any](size int) (Arena[T], error)

func NewMemoryArena

func NewMemoryArena[T any](size int) (Arena[T], error)

NewMemoryArena allocates an arena with at least `size` bytes of usable space. Returned addresses are naturally aligned for *T.

type AtomicArena added in v1.10.15

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

func (*AtomicArena[T]) Allocate added in v1.10.15

func (a *AtomicArena[T]) Allocate(sz int) (unsafe.Pointer, error)

Allocate reserves sz bytes from the arena, aligned to T's alignment, returning a pointer.

func (*AtomicArena[T]) AppendSlice added in v1.10.27

func (a *AtomicArena[T]) AppendSlice(slice []T, elems ...T) ([]T, error)

AppendSlice appends elems to slice backed by this arena, resizing via the arena when needed.

func (*AtomicArena[T]) Base added in v1.10.29

func (a *AtomicArena[T]) Base() unsafe.Pointer

func (*AtomicArena[T]) NewObject added in v1.10.27

func (a *AtomicArena[T]) NewObject(obj T) (*T, error)

NewObject allocates space for T, copies obj into it, and returns *T.

func (*AtomicArena[T]) Offset added in v1.10.29

func (a *AtomicArena[T]) Offset() int

func (*AtomicArena[T]) Reset added in v1.10.15

func (a *AtomicArena[T]) Reset()

Reset zeros used memory and resets the offset to zero. Not safe to call concurrently with Allocate.

type ConcurrentArena

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

func (*ConcurrentArena[T]) Allocate

func (c *ConcurrentArena[T]) Allocate(sz int) (unsafe.Pointer, error)

func (*ConcurrentArena[T]) AppendSlice added in v1.10.23

func (c *ConcurrentArena[T]) AppendSlice(slice []T, elems ...T) ([]T, error)

func (*ConcurrentArena[T]) Base added in v1.10.29

func (ca *ConcurrentArena[T]) Base() unsafe.Pointer

func (*ConcurrentArena[T]) NewObject added in v1.10.23

func (c *ConcurrentArena[T]) NewObject(obj T) (*T, error)

func (*ConcurrentArena[T]) Offset added in v1.10.29

func (c *ConcurrentArena[T]) Offset() int

func (*ConcurrentArena[T]) Reset

func (c *ConcurrentArena[T]) Reset()

type MemoryArena

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

func (*MemoryArena[T]) Allocate

func (a *MemoryArena[T]) Allocate(sz int) (unsafe.Pointer, error)

func (*MemoryArena[T]) AppendSlice added in v1.10.23

func (a *MemoryArena[T]) AppendSlice(slice []T, elems ...T) ([]T, error)

func (*MemoryArena[T]) Base added in v1.10.29

func (a *MemoryArena[T]) Base() unsafe.Pointer

func (*MemoryArena[T]) NewObject added in v1.10.23

func (a *MemoryArena[T]) NewObject(obj T) (*T, error)

NewObject allocates space for T by calling Allocate, copies `obj` into it, and returns *T.

func (*MemoryArena[T]) Offset added in v1.10.29

func (a *MemoryArena[T]) Offset() int

func (*MemoryArena[T]) Reset

func (a *MemoryArena[T]) Reset()

Jump to

Keyboard shortcuts

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