UnmanagedMMU
UnmanagedMMU is a high-performance C# memory manager library that provides efficient unmanaged memory allocation.
Table of Contents
SegmentedPool
A SegmentedPool is a segmented bump allocator for unmanaged memory in C#. It pre-allocates memory in fixed-size segments and serves allocations sequentially within each segment.
Once a segment is full, the pool automatically switches to a new segment, allowing fast, contiguous allocations without fragmentation.
Advantages of the SegmentedPool:
- High performance: Allocation is simple pointer arithmetic.
- Contiguous memory: Reduces cache misses and improves data locality.
- Thread-safe: Supports concurrent allocation operations.
- Manual memory control: Works outside of .NET GC, ideal for high-performance or low-latency scenarios.
Segments
A Segment is a contiguous block of unmanaged memory managed by the pool. Each segment contains:
| Field | Type | Description |
|---|---|---|
Ptr |
byte* |
Pointer to the start of the unmanaged memory block. |
Offset |
nuint |
Current allocation offset within the segment. Increases as memory is allocated. |
Size |
nuint |
Total size of the segment in bytes. |
Segments are allocated automatically by the pool and should never be modified outside the pool.
Allocation Strategy
The SegmentedPool uses a bump allocator strategy:
- Memory is allocated sequentially within the current Segments.
Offsetis incremented with each allocation.- When the current segment does not have enough space, the pool switches to a new Segments (either from the free pool or a freshly allocated one).
This provides O(1) allocation performance for most operations.
Constructor
Initializes a new instance of the SegmentedPool with the specified segment size and number of pre-allocated Segments.
Syntax
SegmentedPool pool = new SegmentedPool(segmentSize: 4 * 1024 * 1024, initialSegments: 4);
Parameters
| Parameter | Type | Description |
|---|---|---|
segmentSize |
nuint |
Size of each Segment in bytes. Optional. Defaults to 4 MiB (4 1024 1024 bytes). |
initialSegments |
int |
Number of Segments to pre-allocate in the pool. Optional. Defaults to 4. |
Return value
Returns a new instance of the SegmentedPool with the specified Segments size and number of pre-allocated Segments.
Remarks
The SegmentedPool pre-allocates the specified number of Segments during construction, ensuring that the pool can immediately serve allocations without additional memory allocation overhead. The pool operates in unmanaged memory and bypasses the .NET garbage collector, so all memory must be manually released by calling Dispose() when the pool is no longer needed.
Allocate
Allocates a span of unmanaged memory for elements of type T from the pool.
Syntax
Span<T> buffer = pool.Allocate<T>(count);
Parameters
| Parameter | Type | Description |
|---|---|---|
count |
int |
Number of elements of type T to allocate. Must be greater than zero. |
Return value
A Span<T> representing the allocated memory. The span is valid until the pool is reset or disposed.
Remarks
Accessing the memory after calling Reset() or Dispose() is undefined behavior and may lead to crashes.
SetSegmentSize
Sets the Segment size to use for future allocations.
Syntax
pool.SetSegmentSize(newSize);
Parameters
| Parameter | Type | Description |
|---|---|---|
newSize |
nuint | The new segment size in bytes. Must be > 0. |
Return value
None.
Remarks
This method will only affect the Segment size of future allocations; it does not modify existing Segments.
ResetSegmentSize
Resets the Segment size for future allocations back to the default (4 MiB).
Syntax
pool.ResetSegmentSize();
Parameters
None.
Return value
None.
Remarks
This method will only affect the Segment size of future allocations; it does not modify existing Segments.
Reset
Resets the pool, returning all active Segments to the free pool for reuse.
Syntax
pool.Reset(trim: false);
Parameters
| Parameter | Type | Description |
|---|---|---|
trim |
bool |
Optional. If true, trims excess free Segments after reset. Defaults to false |
Return value
None.
Remarks
This method resets all active Segments’ offsets to zero. Additionally, no memory is freed unless trim is true; the pool retains free Segments for future allocations.
Trim
Frees unused Segments in the free pool, reducing memory usage.
Syntax
pool.Trim(minFreeSegments: 16);
Parameters
| Parameter | Type | Description |
|---|---|---|
minFreeSegments |
int |
Minimum number of free Segments to retain. Segments beyond this count are released. Defaults to 16. |
Return value
None.
Remarks
This method releases unmanaged memory for excess Segments beyond the specified minimum. This is useful for helping to controlthe unmanaged memory footprint in long-running applications.
Dispose
Releases all unmanaged memory used by the pool and clears internal state.
Syntax
pool.Dispose();
Parameters
None.
Return value
None.
Remarks
This method frees all active and free Segments so that after disposal, any memory allocated from the pool is invalid. This method is safe to call multiple times and calling any other public method after disposal is also safe.