Object Pool - pattern tái sử dụng object để giảm GC pressure, tăng hiệu năng khi tạo/hủy object tốn kém (DB connection, thread, buffer...).
Khi nào dùng
- Object tạo tốn tài nguyên (socket, DB connection, large buffer)
- Tần suất tạo/hủy cao
- Object state có thể reset nhanh
Triển khai cơ bản
using System; using System.Collections.Concurrent; using System.Collections.Generic; public class ObjectPoolwhere T : class, new() { private readonly ConcurrentBag _pool = new ConcurrentBag (); private readonly Func _factory; private readonly Action _reset; public ObjectPool(Func factory = null, Action reset = null) { _factory = factory ?? (() => new T()); _reset = reset ?? (_ => { }); } public T Rent() { if (_pool.TryTake(out T item)) return item; return _factory(); } public void Return(T item) { _reset(item); _pool.Add(item); } } // Sử dụng class ExpensiveResource { public int Id { get; set; } public byte[] Buffer { get; } = new byte[1024 * 1024]; // 1MB public void Reset() => Array.Clear(Buffer, 0, Buffer.Length); } class Program { static void Main() { var pool = new ObjectPool ( factory: () => new ExpensiveResource(), reset: r => r.Reset()); // Thuê object var obj1 = pool.Rent(); obj1.Id = 1; Console.WriteLine($"Rented: {obj1.Id}"); // Trả về pool.Return(obj1); // Thuê lại - có thể nhận object cũ var obj2 = pool.Rent(); Console.WriteLine($"Rented again: {obj2.Id}"); // Có thể là 1 } }
.NET Built-in: ArrayPool<T>
using System.Buffers; var pool = ArrayPool.Shared; byte[] buffer = pool.Rent(1024); // Mượn 1KB try { // Sử dụng buffer } finally { pool.Return(buffer); // Trả về }
Lưu ý: ObjectPoolingAttribute (Enterprise Services) đã cũ. Dùng ArrayPool<T>, MemoryPool<T> hoặc custom pool như trên.