Files
Juliet/AgentData/MemoryArena.md

65 lines
2.9 KiB
Markdown

# 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
```cpp
// 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.