Overview
TheRegionAllocator<T> template class implements a simple region-based memory allocator. It allocates memory in a contiguous region and uses 32-bit references instead of pointers for memory efficiency. This allocator is primarily used in MiniSat for clause storage.
This allocator does not support individual deallocations. It tracks “wasted” space from freed objects but doesn’t reuse it.
Template parameters
The unit type for the region. Typically
uint32_t for byte-level allocation.Type definitions
32-bit reference type used instead of pointers. More compact than 64-bit pointers.
Ref_Undef
Special value representing an undefined/null reference
Unit_Size
Size in bytes of each allocation unit
Constructor and destructor
Initial capacity in units (default is 1MB worth of units)
Size tracking
size
wasted
Monitoring wasted space helps determine when to trigger garbage collection in the solver.
Allocation operations
alloc
Number of units to allocate (must be > 0)
Ref (32-bit reference) to the allocated block
Time complexity: O(1) amortized. May trigger capacity expansion.
free
Number of units to mark as wasted
Reference operations
The allocator provides operations to convert between references and pointers:operator[] (dereference)
Reference to dereference (must be < size())
lea (Load Effective Address)
Reference to convert
ael (Address to reference)
lea).
Pointer within the allocated region
Ref corresponding to the pointer
Capacity management
capacity (internal)
alloc().
Minimum required capacity
uint32_t indices.
Growth sequence ensures maximum use of the 32-bit address space while avoiding overflow.
Transfer operations
moveTo
Destination allocator (its current contents are freed)
Usage example
Typical use in MiniSat
MiniSat usesRegionAllocator<uint32_t> for clause storage:
Design rationale
Why 32-bit references?
- Memory efficiency: Clauses in SAT solvers are small objects referenced frequently. Using 32-bit references instead of 64-bit pointers saves significant memory.
- Cache efficiency: Smaller references improve cache locality.
- Sufficient range: 2³² units provides 16GB of addressable space when
T = uint32_t, which is adequate for most SAT problems.
Why region-based allocation?
- Fast allocation: O(1) bump-pointer allocation
- No fragmentation: All memory is contiguous
- Bulk deallocation: Can free entire region at once during garbage collection
- Simplified management: No need to track individual deallocations
Limitations
- No individual deallocation: Memory marked as “wasted” cannot be reused
- Requires garbage collection: Periodic compaction needed to reclaim wasted space
- Fixed unit size: Cannot efficiently mix allocations of very different sizes
Performance characteristics
- Allocation: O(1) amortized (may trigger realloc)
- Deallocation: O(1) (just increments wasted counter)
- Dereference: O(1) (simple array access)
- Space overhead: One pointer + two 32-bit integers
- Growth factor: 13/8 (approximately 1.625)