多层次缓冲区池 BufferPoolManager

适用场景:
适用于文件上传、图像处理、网络数据传输等大量数据处理时,
内存分配频繁,大对象堆碎片化严重;
GC压力大,频繁触发垃圾回收,导致响应时间不稳定,影响性能,用户体验差;

Demo

var totalProcessed = 0;
var fi = new FileInfo(filePath);
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync: true))
{
    var buffer = _poolManager.GetBuffer((int)fi.Length);
    try
    {
        int bytesRead;
        while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
        {
            // TODO
            totalProcessed += bytesRead;
        }
    }
    finally
    {
        _poolManager.ReturnBuffer(buffer);
    }
}

BufferPoolManager

using Microsoft.Extensions.ObjectPool;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// 多层次缓冲区池管理器
/// </summary>
/// <remarks>根据数据大小智能分配不同规格的缓冲区</remarks>
public class BufferPoolManager
{
    /// <summary>
    /// 8KB
    /// </summary>
    public const int SMALLBUFFERSIZE = 8 * 1024;
    /// <summary>
    /// 64KB
    /// </summary>
    public const int MEDIUMBUFFERSIZE = 64 * 1024;
    /// <summary>
    /// 1MB
    /// </summary>
    public const int LARGEBUFFERSIZE = 1024 * 1024;
    /// <summary>
    /// 8MB
    /// </summary>
    public const int SUPERBUFFERSIZE = 8 * 1024 * 1024;
    /// <summary>
    /// 小文件 8KB
    /// </summary>
    private readonly ObjectPool<byte[]> _smallBufferPool;
    /// <summary>
    /// 中等文件 64KB
    /// </summary>
    private readonly ObjectPool<byte[]> _mediumBufferPool;
    /// <summary>
    /// 大文件 1MB
    /// </summary>
    private readonly ObjectPool<byte[]> _largeBufferPool;
    /// <summary>
    /// 超大文件 8MB
    /// </summary>
    private readonly ObjectPool<byte[]> _superBufferPool;

    /// <summary>
    /// 小文件监控池 使用计数器
    /// </summary>
    private int _smallBufferCount;
    /// <summary>
    /// 中等文件监控池 使用计数器
    /// </summary>
    private int _mediumBufferCount;
    /// <summary>
    /// 大文件监控池 使用计数器
    /// </summary>
    private int _largeBufferCount;
    /// <summary>
    /// 超大文件监控池 使用计数器
    /// </summary>
    private int _superBufferCount;

    public BufferPoolManager()
    {
        _smallBufferPool = new DefaultObjectPool<byte[]>(new BufferPoolPolicy(SMALLBUFFERSIZE));
        _mediumBufferPool = new DefaultObjectPool<byte[]>(new BufferPoolPolicy(MEDIUMBUFFERSIZE));
        _largeBufferPool = new DefaultObjectPool<byte[]>(new BufferPoolPolicy(LARGEBUFFERSIZE));
        _superBufferPool = new DefaultObjectPool<byte[]>(new BufferPoolPolicy(SUPERBUFFERSIZE));
    }

    /// <summary>
    /// 获取缓冲区:根据需要的大小选择合适的池
    /// </summary>
    /// <param name="size">B</param>
    /// <returns></returns>
    public byte[] GetBuffer(int size)
    {
        if (size <= SMALLBUFFERSIZE)
        {
            Interlocked.Increment(ref _smallBufferCount);
            return _smallBufferPool.Get();
        }
        if (size <= MEDIUMBUFFERSIZE)
        {
            Interlocked.Increment(ref _mediumBufferCount);
            return _mediumBufferPool.Get();
        }
        if (size <= LARGEBUFFERSIZE)
        {
            Interlocked.Increment(ref _largeBufferCount);
            return _largeBufferPool.Get();
        }

        Interlocked.Increment(ref _superBufferCount);
        return _superBufferPool.Get();
    }

    /// <summary>
    /// 归还缓冲区到对应的池中
    /// </summary>
    /// <param name="buffer"></param>
    public void ReturnBuffer(byte[] buffer)
    {
        if (buffer.Length <= SMALLBUFFERSIZE)
        {
            Interlocked.Decrement(ref _smallBufferCount);
            _smallBufferPool.Return(buffer);
        }
        else if (buffer.Length <= MEDIUMBUFFERSIZE)
        {
            Interlocked.Decrement(ref _mediumBufferCount);
            _mediumBufferPool.Return(buffer);
        }
        else if (buffer.Length <= LARGEBUFFERSIZE)
        {
            Interlocked.Decrement(ref _largeBufferCount);
            _largeBufferPool.Return(buffer);
        }
        else
        {
            Interlocked.Decrement(ref _superBufferCount);
            _superBufferPool.Return(buffer);
        }
    }

    public string GetDetailInfo()
    {
        return $" 小:{_smallBufferCount} 中:{_mediumBufferCount} 大:{_largeBufferCount} 特大:{_superBufferCount}";
    }
}

/// <summary>
/// 缓冲区池策略:定义如何创建和重用缓冲区
/// </summary>
internal class BufferPoolPolicy : IPooledObjectPolicy<byte[]>
{
    private readonly int _bufferSize;

    public BufferPoolPolicy(int bufferSize)
    {
        _bufferSize = bufferSize;
    }
    /// <summary>
    /// 创建新的缓冲区
    /// </summary>
    /// <returns></returns>
    public byte[] Create()
    {
        return new byte[_bufferSize];
    }
    /// <summary>
    /// 决定对象是否可以重用
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public bool Return(byte[] obj)
    {
        if (obj == null || obj.Length != _bufferSize)
        {
            return false;
        }
        // 这里可以选择清空缓冲区,但会影响性能
        // 在大多数场景下,不清空也是安全的
        // Array.Clear(obj, 0, obj.Length);
        return true;
    }
}
posted @ 2025-09-04 16:38  wesson2019  阅读(5)  评论(0)    收藏  举报