Updated the SegmentedPool to allow for zeroing of allocations and for returning a pointer to allocated memory to allow for use in unsafe structs (#2)

This commit was merged in pull request #2.
This commit is contained in:
Jim
2026-03-20 17:51:15 +00:00
parent dfbdf905fe
commit c2150acb2c
15 changed files with 2788 additions and 674 deletions

611
README.md
View File

@@ -1,27 +1,103 @@
# UnmanagedMMU
# UnmanagedMMU <!-- omit from toc -->
UnmanagedMMU is a high-performance C# memory manager library that provides efficient unmanaged memory allocation.
---
## Table of Contents
## Table of Contents <!-- omit from toc -->
1. [SegmentedPool](#segmentedpool)
- [Segments](#segments)
- [Allocation Strategy](#allocation-strategy)
- [Constructor](#segmentedpool-constructor)
- [Allocate](#segmentedpool-allocate)
- [SetSegmentSize](#segmentedpool-set-segment-size)
- [ResetSegmentSize](#segmentedpool-reset-segment-size)
- [Reset](#segmentedpool-reset)
- [Trim](#segmentedpool-trim)
- [Dispose](#segmentedpool-dispose)
- [IMemoryHandle](#imemoryhandle)
- [IMemoryHandle (Untyped)](#imemoryhandle-untyped)
- [IMemoryHandle\<T\> (Typed)](#imemoryhandlet-typed)
- [SegmentedPool](#segmentedpool)
- [Segments](#segments)
- [SegmentAlignment](#segmentalignment)
- [Allocation Strategy](#allocation-strategy)
- [Constructor](#constructor)
- [Allocation Methods](#allocation-methods)
- [Allocate](#allocate)
- [AllocateAligned](#allocatealigned)
- [Pool State Properties](#pool-state-properties)
- [CurrentSegmentSize](#currentsegmentsize)
- [TotalAllocatedBytes](#totalallocatedbytes)
- [TotalUsedBytes](#totalusedbytes)
- [ActiveSegmentCount](#activesegmentcount)
- [FreeSegmentCount](#freesegmentcount)
- [IsDisposed](#isdisposed)
- [Segment Size Management](#segment-size-management)
- [SetSegmentSize](#setsegmentsize)
- [ResetSegmentSize](#resetsegmentsize)
- [Reset and Trim](#reset-and-trim)
- [Reset](#reset)
- [Trim](#trim)
- [Diagnostics](#diagnostics)
- [GetPoolState](#getpoolstate)
- [GetDiagnosticReport](#getdiagnosticreport)
- [GetCurrentSegmentInfo](#getcurrentsegmentinfo)
- [GetAllSegmentInfos](#getallsegmentinfos)
- [Dispose](#dispose)
---
## SegmentedPool
## IMemoryHandle
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.
The `UnmanagedMMU` namespace provides two interface variations for memory handles. The non-generic IMemoryHandle is a thin wrapper around a pointer for untyped access. The generic IMemoryHandle<T> extends the non-generic interface to provide strong typing and implements IDisposable for automatic resource management.
---
### IMemoryHandle (Untyped)<a id="IMemoryHandle"></a>
The **IMemoryHandle** interface represents a non-generic memory handle. It provides access to the raw pointer and byte count, useful when the element type is unknown at compile time or when interfacing with low-level APIs.
**Key Properties:**
| Property | Type | Description |
| ----------- | ------- | --------------------------------------------- |
| `Pointer` | `void*` | A raw pointer to the start of the allocation. |
| `ByteCount` | `nuint` | The total size of the allocation in bytes. |
### IMemoryHandle\<T\> (Typed)<a id="IMemoryHandleT"></a>
The **IMemoryHandle\<T\>** interface extends [IMemoryHandle](#IMemoryHandle) and provides strongly typed access to the underlying memory. It is the primary interface used with SegmentedPool allocations. This interface implements IDisposable.
**Key Properties:**
| Property | Type | Description |
| ----------- | ------- | --------------------------------------------------------------------- |
| `Pointer` | `T*` | A typed pointer to the start of the allocation. |
| `ByteCount` | `nuint` | The total size of the allocation in bytes. |
| `Length` | `nuint` | The number of `T` elements in the allocation (ByteCount / sizeof(T)). |
**Example Usage:**
```csharp
using var pool = new SegmentedPool();
// Allocate memory for 100 integers
IMemoryHandle<int> handle = pool.Allocate<int>(100);
try
{
// Access via typed pointer
unsafe
{
for (int i = 0; i < handle.Length; i++)
{
handle.Pointer[i] = i;
}
}
}
finally
{
handle.Dispose();
}
```
---
## SegmentedPool<a id="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`:
@@ -30,6 +106,7 @@ Advantages of the `SegmentedPool`:
- **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.
- **Configurable alignment**: Supports SIMD and hardware-specific alignment requirements.
---
@@ -37,16 +114,32 @@ Advantages of the `SegmentedPool`:
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. |
| 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**.
---
### SegmentAlignment<a id="segmentalignment"></a>
The `SegmentAlignment` enum defines the alignment requirements for memory segments. Values are powers of 2 and reflect common hardware requirements (SIMD, cache lines, native pointer size).
| Value | Alignment | Description |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------- |
| `Aligned8` | 8 bytes | Minimum for 64-bit pointers and primitives (long, double). |
| `Aligned16` | 16 bytes | Required for Vector128 (SSE/NEON). Common default for general-purpose SIMD workloads. |
| `Aligned32` | 32 bytes | Required for Vector256 (AVX). Recommended default for SIMD-heavy applications. |
| `Aligned64` | 64 bytes | Matches standard CPU cache-line size. Ensures segment bases align to cache line boundaries, minimizing cache-line splits. |
| `Aligned128` | 128 bytes | Advanced optimization for specific cache-aware algorithms or AVX-512 contexts. |
**Default**: `SegmentAlignment.Aligned32`
---
### Allocation Strategy
The `SegmentedPool` uses a **bump allocator** strategy:
@@ -54,184 +147,552 @@ The `SegmentedPool` uses a **bump allocator** strategy:
1. Memory is allocated sequentially within the current [Segments](#segments).
2. `Offset` is incremented with each allocation.
3. When the current segment does not have enough space, the pool switches to a new [Segments](#segments) (either from the free pool or a freshly allocated one).
4. Allocations are aligned according to the [SegmentAlignment](#segmentalignment) or a requested alignment.
This provides **O(1) allocation performance** for most operations.
---
### Constructor <a name="segmentedpool-constructor"></a>
### Constructor<a id="segmentedpool-constructor"></a>
Initializes a new instance of the SegmentedPool with the specified segment size and number of pre-allocated [Segments](#segments).
Initializes a new instance of the SegmentedPool with the specified segment size, alignment, and number of pre-allocated [Segments](#segments).
#### Syntax
#### Syntax <!-- omit from toc -->
```csharp
SegmentedPool pool = new SegmentedPool(segmentSize: 4 * 1024 * 1024, initialSegments: 4);
// Default configuration
SegmentedPool pool = new SegmentedPool();
// Custom parameters
SegmentedPool pool = new SegmentedPool(
segmentSize: 4 * 1024 * 1024,
segmentAlignment: SegmentAlignment.Aligned32,
initialSegments: 4,
zeroMemory: false
);
```
#### Parameters
#### Parameters<!-- omit from toc -->
| Parameter | Type | Description |
| ----------------- | ------- | ----------------------------------------------------------------------------------- |
| `segmentSize` | `nuint` | Size of each [Segment](#segments) in bytes. Optional. Defaults to 4 MiB (4 *1024* 1024 bytes). |
| `initialSegments` | `int` | Number of [Segments](#segments) to pre-allocate in the pool. Optional. Defaults to 4. |
| Parameter | Type | Description |
| ------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `segmentSize` | `nuint` | Size of each [Segment](#segments) in bytes. Optional. Defaults to 4 MiB (4 * 1024 * 1024 bytes). |
| `segmentAlignment` | `SegmentAlignment` | [Alignment](#segmentalignment) requirement for each allocated [Segment](#segments). Must be a power of 2. Optional. Defaults to **Aligned32**. |
| `initialSegments` | `int` | Number of [Segments](#segments) to pre-allocate in the pool. Optional. Defaults to 4. |
| `zeroMemory` | `bool` | When true, memory returned from the pool is zero-initialized. When false, memory may contain previously used data and it is the caller's responsibility to clear it if required. Optional. Defaults to false. |
#### Return value
#### Return value<!-- omit from toc -->
Returns a new instance of the SegmentedPool with the specified [Segments](#segments) size and number of pre-allocated [Segments](#segments).
#### Remarks
#### Exceptions<!-- omit from toc -->
| Exception | Condition |
| ----------------------------- | -------------------------------------------------------------------- |
| `ArgumentOutOfRangeException` | Thrown if `segmentSize` is zero or `initialSegments` is less than 1. |
| `ArgumentException` | Thrown if `alignment` is not a power of 2. |
#### Remarks<!-- omit from toc -->
The SegmentedPool pre-allocates the specified number of [Segments](#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.
When `zeroMemory` is set to true, all memory returned from the pool is zero-initialized, which ensures that no residual data from previous allocations is exposed.
When `zeroMemory` is false, memory may contain leftover data from prior use, and it is the caller's responsibility to clear it if necessary to maintain data integrity or security.
Setting `zeroMemory` to true may have a slight performance cost due to the additional initialization step.
---
### Allocate <a name="segmentedpool-allocate"></a>
### Allocation Methods<a id="segmentedpool-allocation-methods"></a>
Allocates a span of unmanaged memory for elements of type T from the pool.
The SegmentedPool provides two allocation methods, both returning [IMemoryHandle\<T\>](#IMemoryHandleT) for safe memory management.
#### Syntax
#### Allocate<a id="segmentedpool-allocate"></a>
Allocates a block of unmanaged memory of the specified count for elements of type `T` using the pool's default segment alignment.
##### Syntax<!-- omit from toc -->
```csharp
Span<T> buffer = pool.Allocate<T>(count);
IMemoryHandle<T> handle = pool.Allocate<T>(count);
```
#### Parameters
##### Parameters<!-- omit from toc -->
| Parameter | Type | Description |
| ----------- | ------- | ----------------------------------------------------------------------------- |
| `count` | `int` | Number of elements of type T to allocate. Must be greater than zero. |
| Parameter | Type | Description |
| --------- | ----- | ---------------------------------------------------------------------- |
| `count` | `int` | Number of elements of type `T` to allocate. Must be greater than zero. |
#### Return value
##### Return value<!-- omit from toc -->
A `Span<T>` representing the allocated memory. The span is valid until the pool is reset or disposed.
An [IMemoryHandle\<T\>](#IMemoryHandleT) representing the allocated memory. The handle is valid until either [Reset](#segmentedpool-reset) or [Dispose](#segmentedpool-dispose) is called on the pool.
#### Remarks
##### Remarks<!-- omit from toc -->
Accessing the memory after calling Reset() or Dispose() is undefined behavior and may lead to crashes.
- This allocation is performed in unmanaged memory and bypasses the .NET garbage collector.
- Accessing the memory after [Reset](#segmentedpool-reset) or [Dispose](#segmentedpool-dispose) has been called is undefined behavior.
- Memory alignment is based on the pool's configured [SegmentAlignment](#segmentalignment).
##### Exceptions<!-- omit from toc -->
| Exception | Condition |
| ----------------------------- | ----------------------------------------------------------------------- |
| `ArgumentOutOfRangeException` | Thrown if `count` is less than or equal to zero. |
| `OverflowException` | Thrown if the total allocation size exceeds the maximum allowable size. |
| `ObjectDisposedException` | Thrown if the pool has been disposed. |
##### Example<!-- omit from toc -->
```csharp
using var pool = new SegmentedPool();
IMemoryHandle<byte> handle = pool.Allocate<byte>(100);
try
{
// Access memory through typed pointer
unsafe
{
for (int i = 0; i < handle.Length; i++)
{
handle.Pointer[i] = i;
}
}
}
finally
{
handle.Dispose(); // Returns memory to pool
}
```
---
### SetSegmentSize <a name="segmentedpool-set-segment-size"></a>
#### AllocateAligned<a id="segmentedpool-allocatealigned"></a>
Allocates a block of unmanaged memory with the specified alignment requirement. This is useful for SIMD or hardware-specific operations.
##### Syntax<!-- omit from toc -->
```csharp
IMemoryHandle<T> handle = pool.AllocateAligned<T>(count, alignment);
```
##### Parameters<!-- omit from toc -->
| Parameter | Type | Description |
| ----------- | ------------------ | --------------------------------------------------------------------------------------------------------------- |
| `count` | `int` | Number of elements of type `T` to allocate. Must be greater than zero. |
| `alignment` | `SegmentAlignment` | The [alignment](#segmentalignment) to align the allocation to inside the currently active [Segment](#segments). |
##### Return value<!-- omit from toc -->
An [IMemoryHandle\<T\>](#IMemoryHandleT) representing the allocated memory. The handle is valid until either [Reset](#segmentedpool-reset) or [Dispose](#segmentedpool-dispose) is called on the pool.
##### Remarks<!-- omit from toc -->
- This allocation is performed in unmanaged memory and bypasses the .NET garbage collector.
- Accessing the memory after [Reset](#segmentedpool-reset) or [Dispose](#segmentedpool-dispose) has been called is undefined behavior.
- The alignment requirement must be a power of 2.
- If the requested alignment is less than `sizeof(T)`, the type's natural size is used instead.
##### Exceptions<!-- omit from toc -->
| Exception | Condition |
| ----------------------------- | ----------------------------------------------------------------------- |
| `ArgumentOutOfRangeException` | Thrown if `count` is less than or equal to zero. |
| `OverflowException` | Thrown if the total allocation size exceeds the maximum allowable size. |
| `ObjectDisposedException` | Thrown if the pool has been disposed. |
| `ArgumentException` | Thrown if `alignment` is not a power of 2. |
##### Example<!-- omit from toc -->
```csharp
using var pool = new SegmentedPool(segmentAlignment: SegmentAlignment.Aligned32);
IMemoryHandle<UInt32> handle = pool.AllocateAligned<Vector256>(64, SegmentAlignment.Aligned32);
try
{
unsafe
{
// Perform SIMD operations on aligned memory
for (int i = 0; i < handle.Length; i++)
{
// Process aligned SIMD data
}
}
}
finally
{
handle.Dispose();
}
```
---
### Pool State Properties<a id="segmentedpool-pool-state-properties"></a>
The SegmentedPool provides several read-only properties for monitoring pool state:
#### CurrentSegmentSize<a id="segmentedpool-currentsegmentsize"></a>
Gets the size, in bytes, used when allocating new [Segment](#segments) instances.
##### Syntax<!-- omit from toc -->
```csharp
nuint size = pool.CurrentSegmentSize;
```
##### Return value<!-- omit from toc -->
The size, in bytes, used when allocating new [Segment](#segments).
##### Remarks<!-- omit from toc -->
This reflects the most recently configured size and affects only future [segment](#segments) allocations.
---
#### TotalAllocatedBytes<a id="segmentedpool-totalallocatedbytes"></a>
Gets the total number of bytes that have currently been allocated from the system.
##### Syntax<!-- omit from toc -->
```csharp
nuint allocated = pool.TotalAllocatedBytes;
```
##### Return value<!-- omit from toc -->
The total number of bytes allocated from the system.
##### Remarks<!-- omit from toc -->
This includes memory for all active and free [Segments](#segments).
---
#### TotalUsedBytes<a id="segmentedpool-totalusedbytes"></a>
Gets the total number of bytes currently in use across all active [segments](#segments).
##### Syntax<!-- omit from toc -->
```csharp
nuint used = pool.TotalUsedBytes;
```
##### Return value<!-- omit from toc -->
The total number of bytes currently in use.
##### Remarks<!-- omit from toc -->
This represents the actual data bytes allocated, excluding alignment padding.
#### ActiveSegmentCount<a id="segmentedpool-activesegmentcount"></a>
Gets the number of [segments](#segments) currently in use in the pool.
##### Syntax<!-- omit from toc -->
```csharp
int count = pool.ActiveSegmentCount;
```
##### Return value<!-- omit from toc -->
The number of [segments](#segments) that are currently active and not yet returned to the free pool.
##### Remarks<!-- omit from toc -->
This property is thread-safe and reflects the current state of the pool.
---
#### FreeSegmentCount<a id="segmentedpool-freesegmentcount"></a>
Gets the number of free [segments](#segments) available for reuse in the pool.
##### Syntax<!-- omit from toc -->
```csharp
int count = pool.FreeSegmentCount;
```
##### Return value<!-- omit from toc -->
The number of [segments](#segments) that are currently free and available for reuse.
##### Remarks<!-- omit from toc -->
This property is thread-safe. A value of 0 indicates that the pool will need to allocate a new [segment](#segments) for the next allocation.
---
#### IsDisposed<a id="segmentedpool-isDisposed"></a>
Gets a value indicating whether this instance has been disposed.
##### Syntax<!-- omit from toc -->
```csharp
bool isDisposed = pool.IsDisposed;
```
##### Return value<!-- omit from toc -->
`true` if the pool has been disposed; otherwise `false`.
##### Remarks<!-- omit from toc -->
Once this value is true, any further calls to allocation or management methods will throw a `ObjectDisposedException`.
---
### Segment Size Management<a id="segmentedpool-segment-size-management"></a>
#### SetSegmentSize<a id="segmentedpool-setsegmentsize"></a>
Sets the [Segment](#segments) size to use for future allocations.
#### Syntax
##### Syntax<!-- omit from toc -->
```csharp
pool.SetSegmentSize(newSize);
```
#### Parameters
##### Parameters<!-- omit from toc -->
| Parameter | Type | Description |
| --------- | ----- | ------------------------------------------- |
| `newSize` | nuint | The new segment size in bytes. Must be > 0. |
#### Return value
##### Return value<!-- omit from toc -->
None.
#### Remarks
##### Remarks<!-- omit from toc -->
This method will only affect the [Segment](#segments) size of future allocations; it does not modify existing [Segments](#segments).
##### Exceptions<!-- omit from toc -->
| Exception | Condition |
| ----------------------------- | ------------------------------------- |
| `ArgumentOutOfRangeException` | Thrown if `newSize` is zero. |
| `ObjectDisposedException` | Thrown if the pool has been disposed. |
---
### ResetSegmentSize <a name="segmentedpool-reset-segment-size"></a>
#### ResetSegmentSize<a id="segmentedpool-resetsegmentsize"></a>
Resets the [Segment](#segments) size for future allocations back to the default (4 MiB).
#### Syntax
##### Syntax<!-- omit from toc -->
```csharp
pool.ResetSegmentSize();
```
#### Parameters
##### Parameters<!-- omit from toc -->
None.
#### Return value
##### Return value<!-- omit from toc -->
None.
#### Remarks
##### Remarks<!-- omit from toc -->
This method will only affect the [Segment](#segments) size of future allocations; it does not modify existing [Segments](#segments).
---
### Reset <a name="segmentedpool-reset"></a>
### Reset and Trim<a id="segmentedpool-reset-and-trim"></a>
#### Reset<a id="segmentedpool-reset"></a>
Resets the pool, returning all active [Segments](#segments) to the free pool for reuse.
#### Syntax
##### Syntax<!-- omit from toc -->
```csharp
pool.Reset(trim: false);
```
#### Parameters
##### Parameters<!-- omit from toc -->
| Parameter | Type | Description |
| ----------- | ------- | ----------------------------------------------------------------------------- |
| `trim` | `bool` | Optional. If true, trims excess free [Segments](#segments) after reset. Defaults to false |
| Parameter | Type | Description |
| --------- | ------ | ----------------------------------------------------------------------------------------- |
| `trim` | `bool` | Optional. If true, trims excess free [Segments](#segments) after reset. Defaults to false |
#### Return value
##### Return value<!-- omit from toc -->
None.
#### Remarks
##### Remarks<!-- omit from toc -->
This method resets all active [Segments](#segments) offsets to zero. Additionally, no memory is freed unless trim is true; the pool retains free [Segments](#segments) for future allocations.
This method resets all active [Segments](#segments) offsets to zero. Additionally, no memory is freed unless trim is true; the pool retains free [Segments](#segments) for future allocations.
---
### Trim <a name="segmentedpool-trim"></a>
#### Trim<a id="segmentedpool-trim"></a>
Frees unused [Segments](#segments) in the free pool, reducing memory usage.
#### Syntax
##### Syntax<!-- omit from toc -->
```csharp
pool.Trim(minFreeSegments: 16);
```
#### Parameters
##### Parameters<!-- omit from toc -->
| Parameter | Type | Description |
| ----------- | ------- | ----------------------------------------------------------------------------- |
| `minFreeSegments` | `int` | Minimum number of free [Segments](#segments) to retain. [Segments](#segments) beyond this count are released. Defaults to 16. |
| Parameter | Type | Description |
| ----------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------- |
| `minFreeSegments` | `int` | Minimum number of free [Segments](#segments) to retain. [Segments](#segments) beyond this count are released. Defaults to 16. |
#### Return value
##### Return value<!-- omit from toc -->
None.
#### Remarks
##### Remarks<!-- omit from toc -->
This method releases unmanaged memory for excess [Segments](#segments) beyond the specified minimum. This is useful for helping to controlthe unmanaged memory footprint in long-running applications.
This method releases unmanaged memory from [Segments](#segments) beyond the specified minimum. This is useful for helping to control the unmanaged memory footprint in long-running applications.
##### Exceptions<!-- omit from toc -->
| Exception | Condition |
| ----------------------------- | ---------------------------------------- |
| `ArgumentOutOfRangeException` | Thrown if `minFreeSegments` is negative. |
| `ObjectDisposedException` | Thrown if the pool has been disposed. |
---
### Dispose <a name="segmentedpool-dispose"></a>
### Diagnostics<a id="segmentedpool-diagnostics"></a>
The SegmentedPool provides several diagnostic methods for monitoring pool health and efficiency.
#### GetPoolState<a id="segmentedpool-getpoolstate"></a>
Gets a snapshot of the current pool state for diagnostics.
##### Syntax<!-- omit from toc -->
```csharp
SegmentedPool.PoolState state = pool.GetPoolState();
```
##### Return value<!-- omit from toc -->
A `SegmentedPool.PoolState` struct containing current pool metrics.
##### Example<!-- omit from toc -->
```csharp
var state = pool.GetPoolState();
Console.WriteLine($"Active: {state.ActiveSegmentCount}, Free: {state.FreeSegmentCount}");
Console.WriteLine($"Efficiency: {(100.0 * state.TotalUsed / (state.TotalUsed + state.PaddingBytes)):F0}%");
```
---
#### GetDiagnosticReport<a id="segmentedpool-getdiagnosticreport"></a>
Generates a diagnostic report for the pool including actionable suggestions.
##### Syntax<!-- omit from toc -->
```csharp
string report = pool.GetDiagnosticReport();
```
##### Return value<!-- omit from toc -->
A formatted diagnostic string.
##### Example<!-- omit from toc -->
```csharp
string report = pool.GetDiagnosticReport();
// Output:
// === SegmentedPool Diagnostics ===
// Configuration
// Segment Alignment: 32 bytes (Min Base Alignment)
// Segment Size: 4 MiB
// Segment Summary
// Total Segments: 5 (4 active, 1 free)
// Potential Savings: 0 (via Trim())
// Current Segment
// Base Address: 0x1a2b3c4d
// Offset: 1048576 bytes
// Base Alignment: OK (To 32 bytes)
// Memory Statistics
// Total Reserved: 16 MiB
// Total Used: 8 MiB
// Efficiency: 80% (Good)
// Padding Overhead: 2 MiB
// Allocation Breakdown
// Data Bytes: 8 MiB
// Alignment Padding: 2 MiB
// Total Segment Space: 10 MiB
// Action Required: Pool operating normally.
```
---
#### GetCurrentSegmentInfo<a id="segmentedpool-getcurrentsegmentinfo"></a>
Gets information about the currently active segment. This is the primary diagnostic view for memory usage within the active segment.
##### Syntax<!-- omit from toc -->
```csharp
SegmentedPool.SegmentInfo info = pool.GetCurrentSegmentInfo();
```
##### Return value<!-- omit from toc -->
A `SegmentedPool.SegmentInfo` struct for the current segment.
---
#### GetAllSegmentInfos<a id="segmentedpool-getallsegmentinfos"></a>
Gets a list of all segment details for deep diagnostics. Includes both active and free segments.
##### Syntax<!-- omit from toc -->
```csharp
List<SegmentedPool.SegmentInfo> allSegments = pool.GetAllSegmentInfos();
```
##### Return value<!-- omit from toc -->
A list of `SegmentedPool.SegmentInfo` structs containing all segments.
---
### Dispose<a id="segmentedpool-dispose"></a>
Releases all unmanaged memory used by the pool and clears internal state.
#### Syntax
#### Syntax<!-- omit from toc -->
```csharp
pool.Dispose();
```
#### Parameters
#### Parameters<!-- omit from toc -->
None.
#### Return value
#### Return value<!-- omit from toc -->
None.
#### Remarks
#### Remarks<!-- omit from toc -->
This method frees all active and free [Segments](#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.
After disposal, all allocations become invalid and any further operations will throw [ObjectDisposedException](https://learn.microsoft.com/en-us/dotnet/api/system.objectdisposedexception).