Feature Category
Performance Optimization
Problem / Use Case
Motivation
HashStringAllocator and memory::StlAllocator are Bolt's low-level
allocators, while AlignedBuffer provides the underlying buffer allocation
mechanism for bolt::vector.
HashStringAllocator/ and memory::StlAllocator suffer from performance issues, and AlignedBuffer has lots of internal fragmentation.
-
memory::StlAllocator calls the MemoryPool API directly, which has the
following drawbacks:
- The mutex and locking mechanism in
MemoryPool::allocate is expensive,
resulting in poor allocation performance.
- Mandatory alignment wastes memory.
-
HashStringAllocator was introduced to avoid calling the inefficient
MemoryPool::allocate method directly. Its arena-based memory management
also helps reduce memory fragmentation. However, its implementation has the
following drawbacks:
- Free-list lookup is linear and therefore becomes a performance bottleneck.
- Allocation metadata, such as the pointer and size of every allocation, is
stored in a map and incurs substantial overhead.
-
AlignedBuffer always rounds its capacity up to either a power of two or
1.5 times the previous capacity, which can result in wasted memory due to
internal fragmentation.
Proposed Solution
-
Introduce SlabAllocator as a replacement for memory::StlAllocator.
SlabAllocator reserves memory from MemoryPool in batches, reducing the
frequency of calls to MemoryPool.
-
Introduce MonotonicMemoryResource and its corresponding allocator. They
provide extremely fast allocation and deallocation while eliminating the
metadata overhead of HashStringAllocator.
-
Use allocation strategies tailored to specific use cases. For fixed-size
allocations, account only for SIMD alignment and avoid allocating excess
capacity. For buffers that grow over time, retain the existing growth
strategy to preserve performance.
============================================================================
| [...]s/unstable/SlabAllocatorBenchmark.cpp |
relative |
time/iter |
iters/s. |
| HashStringAllocatorFifoAllocFree256K_8Threads |
|
58.47ns |
17.10M. |
| AlignedStlAllocatorFifoAllocFree256K_8Threads |
10.372% |
563.70ns |
1.77M |
| SlabAllocatorFifoAllocFree256K_8Threads |
384.63% |
15.20ns |
65.79M. |
| case |
time/iter |
allocations |
requested bytes |
reserved bytes |
external peak RSS |
| HashStringAllocatorAllocateNoFree |
4.36s |
54,216,550 |
1,073,741,833 |
0 |
1,354,144 KiB |
| MonotonicMemoryResourceAllocateNoFree |
809.35ms |
54,216,550 |
1,073,741,833 |
2,145,386,496 |
1,099,896 KiB |
SlabAllocator is ~4x faster than HashStringAllocator, and ~38x faster than memory::StlAllocator
- MonotonicMemoryResource is ~5x faster than HashStringAllocator
References / Prior Art
No response
Importance
Blocker (Cannot use Bolt without this)
Willingness to Contribute
Yes, I can submit a PR
Feature Category
Performance Optimization
Problem / Use Case
Motivation
HashStringAllocatorandmemory::StlAllocatorare Bolt's low-levelallocators, while
AlignedBufferprovides the underlying buffer allocationmechanism for
bolt::vector.HashStringAllocator/ andmemory::StlAllocatorsuffer from performance issues, andAlignedBufferhas lots of internal fragmentation.memory::StlAllocatorcalls theMemoryPoolAPI directly, which has thefollowing drawbacks:
MemoryPool::allocateis expensive,resulting in poor allocation performance.
HashStringAllocatorwas introduced to avoid calling the inefficientMemoryPool::allocatemethod directly. Its arena-based memory managementalso helps reduce memory fragmentation. However, its implementation has the
following drawbacks:
stored in a map and incurs substantial overhead.
AlignedBufferalways rounds its capacity up to either a power of two or1.5 times the previous capacity, which can result in wasted memory due to
internal fragmentation.
Proposed Solution
Introduce
SlabAllocatoras a replacement formemory::StlAllocator.SlabAllocatorreserves memory fromMemoryPoolin batches, reducing thefrequency of calls to
MemoryPool.Introduce
MonotonicMemoryResourceand its corresponding allocator. Theyprovide extremely fast allocation and deallocation while eliminating the
metadata overhead of
HashStringAllocator.Use allocation strategies tailored to specific use cases. For fixed-size
allocations, account only for SIMD alignment and avoid allocating excess
capacity. For buffers that grow over time, retain the existing growth
strategy to preserve performance.
============================================================================
SlabAllocatoris ~4x faster thanHashStringAllocator, and ~38x faster thanmemory::StlAllocatorReferences / Prior Art
No response
Importance
Blocker (Cannot use Bolt without this)
Willingness to Contribute
Yes, I can submit a PR