# TEngine Memory Pool Internal Implementation: A Deep Dive into the Generic Object Pool Architecture

> Explore TEngine memory pool internal implementation. Discover its generic object pool architecture, thread-safe MemoryPool facade, and MemoryCollection queues for efficient Unity GC management.

- Repository: [ALEX/tengine](https://github.com/alex-rachel/tengine)
- Tags: internals
- Published: 2026-02-24

---

**TEngine implements a thread-safe, generic object pool through a static `MemoryPool` facade that manages type-specific `MemoryCollection` queues to minimize GC pressure in Unity applications.**

The `alex-rachel/tengine` repository provides a high-performance **TEngine memory pool** designed for Unity game development. This system eliminates runtime allocations for short-lived objects by recycling instances through a centralized, type-safe pooling mechanism.

## Core Architecture Components

The TEngine memory pool architecture consists of four primary components working in concert to provide object lifecycle management.

### MemoryPool Static Facade

The entry point for all pooling operations resides in [`UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPool.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPool.cs). This static partial class exposes the public API including `Acquire<T>()`, `Release(IMemory)`, and bulk operations like `Add()`, `Remove()`, and `ClearAll()`.

At its core, the facade maintains a process-wide dictionary:

```csharp
private static readonly Dictionary<Type, MemoryCollection> _memoryCollections
    = new Dictionary<Type, MemoryCollection>();

```

### MemoryCollection Per-Type Queues

Each pooled type receives a dedicated `MemoryCollection` instance, implemented in [`UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPool.MemoryCollection.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPool.MemoryCollection.cs). This class encapsulates a `Queue<IMemory>` that stores idle objects and tracks real-time usage statistics.

The collection handles the actual allocation and recycling logic. When `Acquire<T>()` is called, the collection either dequeues an existing instance or constructs a new one via `new T()`.

### MemoryPoolInfo Statistics DTO

Diagnostic visibility comes from [`UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPoolInfo.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPoolInfo.cs). This struct captures per-type metrics including:

- `UnusedMemoryCount`: Items waiting in the queue
- `UsingMemoryCount`: Items currently checked out
- `AcquireMemoryCount`: Total acquisitions performed
- `ReleaseMemoryCount`: Total releases performed
- `AddMemoryCount`: Total objects created
- `RemoveMemoryCount`: Total objects removed

## Thread Safety and Synchronization

The TEngine memory pool implements comprehensive thread safety for concurrent environments. Access to the global `_memoryCollections` dictionary is guarded by a `lock` statement, ensuring safe lazy initialization of `MemoryCollection` instances.

Within each `MemoryCollection`, the internal `_memories` queue receives independent synchronization via `lock (_memories)`. This dual-locking strategy allows safe concurrent `Acquire` and `Release` operations across Unity's main thread and background tasks without cross-type contention.

## Strict-Check Validation Mode

The system provides an optional `EnableStrictCheck` mode configurable through [`UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPoolSetting.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/MemoryPool/MemoryPoolSetting.cs). When activated, the pool performs runtime validation through `InternalCheckMemoryType` and the `Release` method.

Strict-check mode validates that:
1. The requested type is a non-abstract class implementing `IMemory`
2. Released instances are not already present in the queue (preventing double-release errors)

## Core API Operations

### Acquiring Objects

The `Acquire<T>()` method in [`MemoryPool.cs`](https://github.com/alex-rachel/tengine/blob/main/MemoryPool.cs) delegates to the type-specific collection:

```csharp
public static T Acquire<T>() where T : class, IMemory, new()
{
    return GetMemoryCollection(typeof(T)).Acquire<T>();
}

```

The collection implementation either recycles an existing instance or allocates a new one, updating `UsingMemoryCount` and `AcquireMemoryCount` accordingly.

### Releasing Objects

The `Release(IMemory memory)` method validates the argument, determines the concrete type, and forwards to the appropriate collection:

```csharp
public static void Release(IMemory memory)
{
    // Validation and type resolution...
    GetMemoryCollection(type).Release(memory);
}

```

The collection clears the object via `memory.Clear()`, optionally checks for duplicates in strict mode, enqueues the instance, and updates release statistics.

### Bulk Operations

The pool supports batch management through `Add<T>(int count)` and `Remove<T>(int count)` methods. `Add` pre-populates the pool with new instances, useful for warm-up phases. `Remove` dequeues and discards specified quantities of idle objects, reducing memory footprint during low-usage periods.

`ClearAll()` iterates every `MemoryCollection`, calls `RemoveAll()`, and clears the global dictionary, effectively resetting the entire pool state.

## Performance Monitoring and Debugging

The `GetAllMemoryPoolInfos()` method aggregates statistics from all collections into `MemoryPoolInfo` arrays. This data feeds the **Memory Pool** tab in TEngine's built-in debugger window (`DebuggerModule.MemoryPoolInformationWindow`), enabling runtime visualization of:

- Memory leaks (indicated by perpetually high `UsingMemoryCount`)
- Over-allocation (high `AddMemoryCount` relative to actual usage)
- Pool efficiency (ratio of `AcquireMemoryCount` to `AddMemoryCount`)

## Implementation Example

Any class implementing `IMemory` (requiring a `Clear()` method) can utilize the pool:

```csharp
public class AssetObject : IMemory
{
    public string AssetName { get; set; }
    public int ReferenceCount { get; set; }

    public void Clear()
    {
        AssetName = null;
        ReferenceCount = 0;
    }
}

// Warm-up
MemoryPool.Add<AssetObject>(100);

// Runtime usage
AssetObject obj = MemoryPool.Acquire<AssetObject>();
obj.AssetName = "HeroTexture";
// ... use object ...
MemoryPool.Release(obj);

// Cleanup
MemoryPool.ClearAll();

```

## Summary

- **TEngine memory pool** uses a static `MemoryPool` facade with type-specific `MemoryCollection` queues to recycle objects implementing `IMemory`.
- Thread safety is achieved through dual-level locking on the global dictionary and individual collection queues.
- Strict-check mode provides runtime validation against double-releases and invalid type requests.
- Comprehensive statistics via `MemoryPoolInfo` enable leak detection and performance tuning through the built-in debugger.
- The implementation resides primarily in [`MemoryPool.cs`](https://github.com/alex-rachel/tengine/blob/main/MemoryPool.cs) and [`MemoryPool.MemoryCollection.cs`](https://github.com/alex-rachel/tengine/blob/main/MemoryPool.MemoryCollection.cs) within the `alex-rachel/tengine` repository.

## Frequently Asked Questions

### What types of objects can be pooled in TEngine?

Any non-abstract class implementing the `IMemory` interface can be pooled. This interface requires a single `Clear()` method that resets the object's state upon release. Common use cases include data transfer objects like `AssetObject`, state machines such as `Fsm<T>`, and temporary containers for loading operations.

### How does TEngine prevent memory leaks in the memory pool?

The pool tracks `UsingMemoryCount` for each type, representing objects currently acquired but not released. If this count grows indefinitely while `Release` calls remain low, the debugger's Memory Pool tab will highlight the leak. Additionally, strict-check mode validates that released instances aren't already in the idle queue, preventing logic errors that could corrupt pool state.

### Is the TEngine memory pool thread-safe for concurrent access?

Yes. The implementation uses two levels of synchronization: a global lock protects the `Dictionary<Type, MemoryCollection>` in [`MemoryPool.cs`](https://github.com/alex-rachel/tengine/blob/main/MemoryPool.cs), while each `MemoryCollection` maintains its own lock on the internal `Queue<IMemory>`. This design allows different types to be acquired and released concurrently without contention, while ensuring thread safety for operations on the same type.

### What is the performance overhead of using strict-check mode?

Strict-check mode adds runtime validation overhead by checking type constraints in `InternalCheckMemoryType` and scanning the queue for duplicate instances during `Release`. While negligible for development and debugging builds, these operations involve reflection and linear queue searches that could impact performance in high-frequency allocation scenarios. Production builds typically disable strict-check mode via `MemoryPoolSetting` to maximize throughput.