Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Object Pool trong C#

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 ObjectPool where 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.