Arena is a high-performance memory allocation library inspired by Google Chrome project, providing efficient memory management with improved data locality and automatic cleanup.
Arena is designed to align heap memory layout with OS/hardware memory paging functions, providing several key benefits:
- Better Data Locality: More gathered heap layout improves cache performance
- CPU-Optimized Alignment: All memory blocks are aligned to CPU word size, preventing cache line pollution
- Simplified Memory Management: No need to call delete/free functions - Arena destroys entire memory blocks in a single operation
- Object Lifecycle Management: Associated objects are destroyed at a single point
- STL Container Optimization: With C++20 power, standard containers can use Arena to optimize memory layout
Note: C++ program's standard containers often have poor memory locality because STL's default allocator creates scattered memory layouts.
Arena uses padding to optimize CPU cache line usage, which results in higher memory overhead but significantly better performance for allocation-heavy workloads.
- C++20 Standard: Full C++20 support required
- std::source_location: Required (note: Apple Clang may not support this yet)
Arena works seamlessly with:
- tcmalloc, jemalloc, and other malloc implementations
- Seastar for shared-nothing architecture
An Arena maintains a chain of memory blocks, where each block is a linear continuous memory area:
+-------+ +-------+
+------+ |Cleanup| +------+ |Cleanup|
|Header| | Area | |Header| | Area |
+------+ +-------+ +------+ +-------+
+------+-----------+---+ +-----+------------+-------+
| | | | | | | |
| | | | | | | |
| | | | <-----+ limit_ ----> |
+->| | | | | | | |
| | | | | | | | |
| | | | | <-----+---- size_ -+------->
| | | | | | | | |
| +---+--+-----------+---+ +--+--+------------+-------+
| | |
| | | +------+
<------+------+ | | Prev |
| +----------------+ | +------+
| | Prev = nullptr | |
| +----------------+ |
| |
| |
+-------------------------------------+
Aligned memory allows CPUs to work in optimal conditions. Modern CPUs have complex memory and cache mechanisms designed specifically for aligned memory access patterns.
The cleanup area stores destructor information for proper object lifecycle management. When the arena is destroyed or reset, all registered cleanup functions are called automatically.
Arena defines two important tags for type management:
- ArenaFullManagedTag - Indicates the class can be created and managed by Arena
- ArenaManagedCreateOnlyTag - Indicates Arena should skip calling the destructor
A class can be created in Arena if it meets ANY of these conditions:
- Simple C-like structs:
is_trivial && is_standard_layout - Tagged classes: Contains
ArenaFullManagedTagorArenaManagedCreateOnlyTag
- is_trivial: Default constructor and copy constructor must be compiler-generated
- is_standard_layout: Simple memory layout with consistent access control, no virtual functions, no non-static reference members, no multiple inheritance
Simple structs that meet trivial and standard layout requirements:
/*
* Simplest struct - no tags needed
* Can be Created and CreateArray
*/
struct simple_struct {
int value;
char flag;
};
Arena arena;
auto* obj = arena.Create<simple_struct>();
auto* array = arena.CreateArray<simple_struct>(100);struct base {
int base_value;
};
/*
* Derived class maintaining standard_layout
* Can be Created and CreateArray
*/
class derived_standard : public base {
public:
int derived_value;
};
Arena arena;
auto* obj = arena.Create<derived_standard>();/*
* Not trivial due to custom constructor
* Cannot be Created without proper tag
*/
class complex_class {
public:
complex_class(int value) : data(value) {}
ArenaFullManagedTag; // Required for Arena creation
private:
int data;
};
Arena arena;
auto* obj = arena.Create<complex_class>(42);/*
* Not standard_layout due to reference member
* Requires ArenaFullManagedTag to be Created in Arena
*/
class arena_aware_class {
public:
arena_aware_class(Arena& a) : arena_ref(a) {}
ArenaFullManagedTag;
private:
Arena& arena_ref;
};
Arena arena;
auto* obj = arena.Create<arena_aware_class>(); // Arena ref passed automaticallyArena integrates seamlessly with C++17 PMR (Polymorphic Memory Resources):
Arena arena;
// Create PMR containers using Arena's memory resource
auto* vec = arena.Create<std::pmr::vector<int>>();
auto* str = arena.Create<std::pmr::string>();
auto* map = arena.Create<std::pmr::unordered_map<int, std::pmr::string>>();
// All allocations from these containers will use Arena memory
vec->push_back(42);
*str = "Hello Arena!";
(*map)[1] = "First entry";class arena_vector {
public:
arena_vector(Arena& a) : arena_ref(a), data(a.get_memory_resource()) {}
ArenaManagedCreateOnlyTag; // Skip destructor - Arena handles cleanup
private:
Arena& arena_ref;
std::pmr::vector<int> data;
};
Arena arena;
auto* container = arena.Create<arena_vector>();class pointer_holder {
public:
pointer_holder(some_type* ptr) : internal_ptr(ptr) {}
ArenaFullManagedTag;
private:
some_type* internal_ptr; // Must outlive the Arena
};
Arena arena;
some_type* long_lived_object = get_long_lived_object();
auto* holder = arena.Create<pointer_holder>(long_lived_object);class multi_arena_class {
public:
multi_arena_class(Arena* other) : other_arena(other) {}
ArenaFullManagedTag;
private:
Arena* other_arena; // Can reference different Arena
};
Arena arena1, arena2;
auto* obj = arena1.Create<multi_arena_class>(&arena2);- Arena Reference as First Parameter: When a class constructor needs an Arena reference, make it the first parameter.
Create()will automatically pass*this:
class arena_class {
arena_class(Arena& arena) : arena_ref(arena) {}
ArenaFullManagedTag;
private:
Arena& arena_ref;
};
Arena arena;
auto* obj = arena.Create<arena_class>(); // Arena ref passed automatically- Additional Parameters: Pass other parameters normally:
class parameterized_class {
parameterized_class(Arena& arena, int value, const std::string& name)
: arena_ref(arena), value_(value), name_(name) {}
ArenaFullManagedTag;
private:
Arena& arena_ref;
int value_;
std::string name_;
};
Arena arena;
auto* obj = arena.Create<parameterized_class>(42, "example");- Single Ownership: An instance should either be completely Arena-managed or not at all
- Cross-Arena Copying: If copying between Arenas, ensure proper resource management
- Same-Arena Moving: Move operations should only occur within the same Arena
- Cleanup Consistency: Use
ArenaManagedCreateOnlyTagwhen Arena handles all cleanup
void advanced_pmr_usage(Arena& arena) {
// Create containers directly in Arena memory
auto* str_vec = arena.Create<std::pmr::vector<std::pmr::string>>();
// Create string directly in vector (no copy)
str_vec->emplace_back("direct_construction_in_arena");
// This involves copying
std::pmr::string temp_str("temporary", arena.get_memory_resource());
str_vec->push_back(temp_str);
}Arena includes built-in metrics for monitoring allocation patterns and performance:
Arena arena;
// ... use arena for allocations ...
// Get allocation statistics
auto stats = arena.get_metrics();
std::cout << "Allocations: " << stats.allocation_count << std::endl;
std::cout << "Memory used: " << stats.bytes_allocated << std::endl;Arena provides clear error conditions:
- Allocation Failure: Returns
nullptrwhen memory cannot be allocated - Type Constraint Violations: Compile-time errors for unsupported types
- Lifecycle Violations: Runtime assertions for improper usage patterns
Arena instances are not thread-safe by default. For multi-threaded usage:
- Use separate Arena instances per thread
- Implement external synchronization for shared Arenas
- Consider thread-local Arena instances for best performance
- Allocation: O(1) amortized
- Deallocation: O(1) for entire Arena, individual objects cannot be freed
- Memory Overhead: Higher due to alignment padding
- Cache Performance: Significantly better due to improved locality
When migrating from standard allocators:
- Replace
new/deletewitharena.Create<T>() - Replace
malloc/freewitharena.AllocateAligned() - Update containers to use
std::pmrvariants with Arena's memory resource - Add appropriate tags to custom classes
- Ensure proper Arena lifetime management
- Enhanced C++20 syntax modernization
- Comprehensive API documentation generation
- Additional performance optimization hooks
- Extended STL container integration