Files
Juliet/AgentData/MemoryArena.md

2.9 KiB

Paged Memory Arena Architecture

Status

Implemented & Active (Jan 2026)

Overview

The memory system uses a Paged Arena model backed by global Memory Pools. This architecture supports indefinite growth, efficient clearing, and minimizes OS-level allocations by sub-allocating from large pre-reserved buffers.

Architecture

1. Memory Pool (MemoryPool)

A Global Source of memory blocks.

  • Role: Manages a large contiguous memory region (e.g., 512MB for Game).
  • Implementation: Free List Allocator.
  • Operations: AllocateBlock (First-Fit with Splitting), FreeBlock (Returns to list).
  • Optimization: Block Splitting is implemented to preserve free space. If a block in the free list is significantly larger than requested (Alloc + Header + 16 bytes), it is split, and the remainder is returned to the free list. This prevents pool exhaustion from small allocations consuming large blocks.
  • Instances:
    • g_EngineMemory (256MB)
    • g_GameMemory (512MB)
    • g_ScratchMemory (64MB)

2. Memory Arena (MemoryArena)

A High-Level Allocator.

  • Structure: A linked list of MemoryBlocks.
  • Behavior:
    • Growth: Starts with one block. If an allocation exceeds capacity, it requests a new Block (Page) from the backing Pool and links it.
    • Alloc: Linear bump-pointer within the current block.
    • Clear: Returns all blocks (except the first) to the Pool. Resets the first block.
    • Realloc: Supports in-place expansion (if top of stack) or copy-and-move.
  • Instances: GetGameArena(), GetEngineArena(), GetScratchArena().

3. Memory Block (MemoryBlock)

The unit of exchange between Pool and Arena.

  • Header: Includes Magic (debug safety), Next pointer, TotalSize (renamed from Size), and Used offset.
  • Alignment: 16-byte alignment enforced.
  • Safety: Debug builds use memory poisoning (0xCD on alloc, 0xDD on free) and Magic number checks to detect corruption.

4. Arena Pop (ArenaPop)

Support for LIFO allocations (reclaiming memory).

  • Behavior: Checks if the pointer is at the very top of the stack (CurrentBlock->Used).
  • Optimization: If valid, decrements Used to reclaim space. If not (fragmented), does nothing.
  • Usage: Critical for ImGui vector resizing to prevent exponential memory consumption.

Usage

// 1. Get an Arena
MemoryArena* arena = GetScratchArena();

// 2. Push Data
MyStruct* data = ArenaPushType<MyStruct>(arena, "Tag");
void* raw = ArenaPush(arena, 1024, 16, "RawBuffer");

// 3. Pop Data (LIFO)
ArenaPop(arena, raw, 1024); // Reclaims memory

// 4. Reset (Scratch only)
ScratchArenaReset(); // Returns pages to g_ScratchMemory

Migration Status

  • ImGui: Migrated to GetEngineArena() (Paged) with ArenaPop support for efficient vector resizing.
  • Display/Window: Uses Engine Arena.
  • Game Entities: Uses Game Arena.