Skip to content

Arena Memory Management

Arena allocation lets you allocate multiple objects and free them all at once when a scope ends.

Basic Usage

def main() -> int:
    using arena:
        let buffer = arena.alloc(1024)  # Allocate 1KB
        let data = arena.alloc(256)     # Allocate 256 bytes
        # Use buffer and data...
    # All arena memory freed automatically here
    return 0

Benefits

  • Fast allocation: Simple bump pointer (constant time)
  • Bulk deallocation: All memory freed at once
  • No memory leaks: Scope-based automatic cleanup
  • No use-after-free: Memory valid for entire scope

Multiple Allocations

def process_batch() -> none:
    using arena:
        let header = arena.alloc(64)
        let body = arena.alloc(4096)
        let footer = arena.alloc(32)

        # All three are valid throughout the scope
        process(header, body, footer)
    # Entire arena freed here
    return

Nested Arenas

Use nested arenas for different lifetimes:

def complex_work() -> none:
    using outer:
        let persistent = outer.alloc(1024)

        for i: int in range(100):
            using inner:
                let temp = inner.alloc(512)
                process(temp, persistent)
            # inner freed each iteration

        finalize(persistent)
    # outer freed here
    return

Use Cases

Request Handling

def handle_request(req: Request) -> Response:
    using arena:
        let parsed = parse_json(req.body, arena)
        let result = process(parsed, arena)
        return result.clone()  # Clone to escape arena

Game Loops

def game_loop():
    while running:
        using frame:
            let entities = frame.alloc(1024)
            update_physics(entities)
            render(entities)
        # Frame data freed - no GC pause!

Automatic Function-Local Arenas

Desi compilers statically perform escape analysis on local variables. If the compiler determines that a heap-allocated collection (such as a list, dict, set, or tuple) does not escape the function scope, it will automatically promote the allocation to a function-local arena.

The compiler automatically takes care of creating the arena, allocating the local collections from it, suppressing individual reference-count/drop operations, and destroying the arena on function exit. You do not need to write using arena: for function-local collections.

Rules

Do Don't
Allocate temporary data Store arena pointers in objects
Nest arenas for lifetimes Use for long-lived data
Clone data that escapes Expect individual frees

Quick Reference

using arena:              # Create arena
    let p = arena.alloc(size)  # Allocate bytes
    # Use p...
# Automatic cleanup