Object Pooling¶
The Object Pooling system in Nalix.Framework provides a thread-safe, high-performance mechanism for recycling expensive class instances, reducing the frequency of garbage collection.
Object Pool Interaction Flow¶
The following diagram illustrates the lifecycle of a poolable object from creation to reuse.
flowchart LR
Start[Request Object] --> Cache{Available in Pool?}
Cache -- Yes --> Get[Retrieve from Storage]
Cache -- No --> Build[Create new Instance]
Get --> Use[Use Object]
Build --> Use
Use --> Return[Return to Pool]
Return --> Reset[Reset State IPoolable]
Reset --> Check{Capacity Full?}
Check -- No --> Save[Store for Reuse]
Check -- Yes --> Dispose[Dispose and GC]
Source Mapping¶
src/Nalix.Abstractions/IPoolable.cssrc/Nalix.Framework/Memory/Pools/ObjectPool.cssrc/Nalix.Framework/Memory/Objects/ObjectPoolManager.cssrc/Nalix.Framework/Memory/Objects/TypedObjectPool.cs
IPoolable Interface¶
Any class intended for pooling must implement IPoolable.
public interface IPoolable
{
/// <summary>
/// Resets the object state to its default values before being returned to the pool.
/// </summary>
void Reset();
}
State Management
Correctly implementing Reset() is critical. Failure to clear collections or reset properties can lead to "polluted" objects being served in future requests.
ObjectPoolManager¶
ObjectPoolManager is the central registry for all typed pools. It maintains statistics, performs health checks, and handles background trimming.
Key Features¶
- Dynamic Creation: Pools are created lazily for each type as needed.
- Typed Pools: Provides
TypedObjectPool<T>for high-performance, type-safe access. - Health Monitoring: Tracks cache hits, misses, and Peak Concurrent Usage.
- Advanced Diagnostics: Optional deep tracking for object lifetimes (avg/p95/max), outstanding counts, suspicious long-lived objects, and GC leak detection.
- Trimming: Supports scheduled or manual trimming to release objects back to the GC during low-load periods.
Key API Members¶
| Member | Description |
|---|---|
Get<T>() |
Retrieves an item from the pool for type T. Creates a new one if the pool is empty. |
Return<T>(obj) |
Resets and returns an object to the pool. |
GetTypedPool<T>() |
Gets or creates a type-specific TypedObjectPool<T> adapter. |
Prealloc<T>(count) |
Force-fills the pool with a specific number of instances (useful at startup). |
SetMaxCapacity<T>(maxCapacity) |
Sets the maximum capacity for a specific type's pool. |
ResetMetrics() |
Resets all global and per-pool metrics to baseline (zero). |
ClearPool<T>() |
Clears all objects from a specific type's pool. |
ClearAllPools() |
Clears all objects from all pools. |
TrimAllPools(percentage = 50) |
Trims all pools to their target sizes. |
ScheduleRegularTrimming(interval, percentage = 50, ct) |
Schedules a background trimming loop. |
PerformHealthCheck() |
Identifies "unhealthy" pools (those with consistently high miss rates). |
ResetStatistics() |
Resets all statistics for the pool manager and all pools. |
GetTypeInfo<T>() |
Gets detailed information about a specific type's pool. |
GenerateReport() |
Produces a detailed text summary of all managed pools and their metrics. |
GetReportData() |
Returns a structured dictionary for monitoring dashboards. |
Properties¶
| Property | Type | Description |
|---|---|---|
DefaultMaxPoolSize |
int |
Default maximum size for new pools (default 1024). |
PoolCount |
int |
Total number of pools currently managed. |
PeakPoolCount |
int |
Peak number of pools at any time. |
TotalGetOperations |
long |
Total number of get operations performed. |
TotalReturnOperations |
long |
Total number of return operations performed. |
TotalCacheHits |
long |
Total number of cache hits. |
TotalCacheMisses |
long |
Total number of cache misses. |
CacheHitRate |
double |
Overall cache hit rate as a percentage (0-100). |
Uptime |
TimeSpan |
Uptime of the pool manager. |
UnhealthyPoolCount |
int |
Number of unhealthy pools. |
TypedObjectPool<T>¶
For performance-critical code, it is recommended to cache a TypedObjectPool<T> rather than calling the manager directly.
// Recommended performance pattern
private readonly TypedObjectPool<MyPacket> _pool =
ObjectPoolManager.Instance.GetTypedPool<MyPacket>();
public void Process()
{
var item = _pool.Get();
try { /* ... */ }
finally { _pool.Return(item); }
}
Monitoring and Health¶
The manager tracks several critical metrics to help tune pool capacities:
- Hit Rate: The percentage of requests satisfied by the pool without creating a new object.
- Outstanding: Number of objects currently held by application code (requires
EnableDiagnostics). - Peak Outstanding: The high-water mark of concurrent objects active at any time (requires
EnableDiagnostics). - Consecutive Failures: High number of cache misses in sequence, suggesting the pool capacity is too low for the current load.
Advanced Diagnostics¶
Advanced diagnostics can be enabled via ObjectPoolOptions (usually in default.ini under [ObjectPool]). These features provide deep insight at a slight performance cost.
Statistics Collected¶
- Lifetime (Avg/p95/Max): How long objects stay rented. High values might indicate slow processing segments.
- Suspicious Objects: Objects held longer than a configurable threshold (e.g., 30s) are listed in reports with their allocation stack trace.
- GC Leak Detection: Uses sentinel finalizers to detect and report objects that were garbage collected without being returned to the pool.
Configuration Example¶
[ObjectPool]
EnableDiagnostics = true
CaptureStackTraces = true
EnableLeakDetection = true
SuspiciousThresholdSeconds = 30
Diagnostic Insight
Use ScheduleRegularTrimming to keep memory usage balanced. Trimming runs PerformHealthCheck automatically to log warnings about unhealthy pools.