This library is a dynamic 2D rectangle allocator intended for atlas-like workloads that need both allocation and deallocation, such as temporary icons, glyphs, or other reusable subregions.
- Dynamic rectangle allocation and deallocation.
- Single-header and module-friendly interface.
- Supports custom allocators for internal containers and nested body allocators.
- Not thread-safe.
- Never rotates allocated regions.
- Never moves a region after allocation.
- Does not provide a strong exception guarantee.
- Public headers are under
include/mo_yanxi/.
void foo(){
mo_yanxi::allocator2d<> a{{256, 256}};
const unsigned width = 32;
const unsigned height = 64;
if(const std::optional<mo_yanxi::math::usize2> where = a.allocate({width, height})){
// Do something here...
a.deallocate(where.value());
}
}- Standard random workload.
- High-fragmentation small-rectangle workload.
- Fully aligned 16x16 workload.
- Performance benchmarks are provided by
Google Benchmarkinbenchmarks/allocator2d_benchmark.cpp - Cross-library benchmark results and charts are provided in
profile/benchmark/CROSS_LIBRARY_RESULTS.md - Validation tests are provided by
GoogleTestintests/allocator2d_test.cpp - Runnable visual sample code is kept in
examples/run_sample.cpp - Generated sample images are written to
readme_assets/ - Local profiling and benchmark artifacts are organized under
profile/
The benchmark compares allocator2d against a small set of C/C++ rectangle packers using the same three workloads.
Full numbers and raw CSV output are in profile/benchmark/CROSS_LIBRARY_RESULTS.md and profile/benchmark/data/cross_library_results.csv.
cmake -S . -B build
cmake --build build --target allocator2d allocator2d_tests allocator2d_benchmark --config Debug
ctest --test-dir build -C Debug --output-on-failure
build\Debug\allocator2d_benchmark.execmake -S . -B build-visual -DENABLE_TEST=ON
cmake --build build-visual --target allocator2d --config Debug
build-visual\Debug\allocator2d.exe| Test Case | Initial Allocate | Partial Deallocate | Refill After Fragmentation |
|---|---|---|---|
| Standard | ![]() |
![]() |
![]() |
| HighFragment | ![]() |
![]() |
![]() |
| Aligned | ![]() |
![]() |
![]() |
The visual sample currently runs six phases per case: initial fill, first fragmentation, first refill, second fragmentation, second refill, and final full reclamation check. The table above shows the first three image-producing stages.
- Prefer tighter-fitting free regions.
- Track reusable free fragments after partial deallocation.
- Split a region into two subregions when there is remaining space.
- A deallocated region that cannot yet be fully merged can still remain reusable through nested/body allocation.
- Input the extent you need.
- Returns the bottom-left point of the allocated region, or
nulloptif no suitable space is available. - The allocated area is never moved.
- Input the position returned by
allocate. - Returns
falseif the point does not identify a currently allocated root in this allocator. In normal usage this should be treated as a logic error, similar to a double-free.
- Copy construction and copy assignment are protected.
- After move, the source allocator is left in a moved-from state and should not be relied on without reassignment.
mo_yanxi::allocator2d_checkedperforms a leak check on destruction.- If
remain_area()does not equal the total extent area, it invokesMO_YANXI_ALLOCATOR_2D_LEAK_BEHAVIOR(*this)when provided; otherwise it prints an error and callsstd::terminate().
- Macro
MO_YANXI_ALLOCATOR_2D_USE_STD_MODULEswitches the header to useimport std;. - Macro
MO_YANXI_ALLOCATOR_2D_HAS_MATH_VECTOR2allows reusing an externalmo_yanxi::math::vector2implementation.








