An extremely fast, extremely cross-platform, zero-dependency Memory Arena and String Pool library for C/C++
Designed for game engines, compilers, and high-performance systems, this library provides malloc and free.
- Zero-Cost Allocations: Allocations take a single CPU cycle thanks to simple pointer addition.
- Universal Cross-Platform: Perfectly aligns memory across 64-bit (Windows, macOS, Linux), 32-bit (Raspberry Pi, legacy, etc), and Apple Silicon.
- Virtual Memory Backend: Uses
mmap(POSIX) andVirtualAlloc(Windows) for instant, massive address space reservation without physical RAM commit. - Malloc Fallback: Seamlessly degrades to standard heap chaining on systems without Virtual Memory, this allows for extreme backwards compatibility
- Scoped Memory (TempArena): Instantly rewind and garbage-collect temporary allocations without any memory leaks.
- String Pool Subsystem: High-performance string interning, deduplication, and variadic
printfformatting.
This library is distributed as a CMake target. The easiest way to include it in your project is via a Git Submodule.
git submodule add https://github.com/redstarbird/MicroArenaAllocator.git external/ArenaAllocator# Add the submodule
add_subdirectory(external/ArenaAllocator)
# Link it to your executable
add_executable(YourProgram src/main.c)
target_link_libraries(YourProgram PRIVATE MemoryArena)# Generate the build files
cmake -B build
# Compile the project
cmake --build build --config Release#include <MemoryArena.h>
int main() {
// Reserve a 16MB virtual memory arena (aborts on Out-of-Memory)
struct MemoryArena* arena = CreateArena(MB(16), OOM_ABORT, NULL);
// O(1) Allocations
float* positions = PushArray(arena, float, 1000);
Entity* player = PushStruct(arena, Entity);
// Instantly free all 1001 allocations at once
DestroyArena(arena);
return 0;
}// Use a temporary arena for each frame
void ProcessFrame(struct MemoryArena* globalArena) {
// Start a temporary scope
struct TempArena temp = BeginTempArena(globalArena);
// Do heavy math, allocate temporary matrices, etc. ...
Matrix* mathBuffer = PushArray(globalArena, Matrix, 500);
// Instantly rewind the arena. The mathBuffer memory is safely freed
// and ready to be overwritten in the next frame
EndTempArena(temp);
}#include <StringPool.h>
void LoadAssets(struct StringPool* pool) {
// Safely formats and deduplicates the string instantly
struct StringView tex1 = InternStringFormat(pool, "textures/%s_%d.png", "player", 1);
struct StringView tex2 = InternStringFormat(pool, "textures/%s_%d.png", "player", 1);
// Both tex1.data and tex2.data will point to the exact same memory address thanks to interning
}By design, MicroMemoryArena is not thread safe.
This library is designed to be as efficient as possible so having locking mechanisms such as OS mutexes or atomic hardware locks would kill the
To safely use multi-threading with this library, do not share a single arena across multiple threads/workers. Instead, use Thread-Local Storage to give a separate, private, lock-free arena to each thread.
// Thread locking example using _Thread_local
_Thread_local struct MemoryArena* threadArena = NULL;
void WorkerThread() {
if (!threadArena) {
threadArena = CreateArena(MB(16), OOM_ABORT, NULL);
}
// Safe, effecient parallel allocations
}Thread safety may be added in a future release of this library.
You can customize the library's behavior when configuring your CMake project using the following options:
| CMake option | Default | Description |
|---|---|---|
| FORCE_MALLOC_FALLBACK | OFF | Forces the use of fall-back malloc block-chaining instead of Virtual Memory. |
| BUILD_32_BIT | OFF | Compiles the library in 32-bit mode |
| ARENA_ENABLE_ASAN | OFF | (Internal) Enables AddressSanitizer, shouldn't be used when linking to this library |
This project is licensed under the MIT License - see the LICENSE file for details.