.Net对象池ObjectPool

简介

对象池化技术可以显著地提升性能,尤其是当对象的初始化过程代价较大或者频率较高。
它是一种基于使用预先分配资源集合的性能优化思想,简单说对象池就是对象的容器,当一个对象被激活时,便被从池中取出,当对象被停用时,它又被放回池中。
在一些对性能比较敏感的应用中,我们可以通过对象复用的方式避免垃圾对象的产生,进而避免GC因对象回收导致的性能损失。
对象池由Microsoft.Extensions.ObjectPool这个NuGet包提供

重要接口/类

ObjectPool:对象池

当我们需要消费某个对象的时候,不会直接创建它,而是选择从对象池中“借出”一个对象。如果对象池为空,或者现有的对象都正在被使用,它会自动帮助我们完成对象的创建。借出的对象不再使用的时候,我们需要及时将其“归还”到对象池中以供后续复用。

T Get():从对象池中借对象。
void Return(T obj):将对象还回对象池中。

DefaultObjectPool:对象池的默认实现类

它实现了Get和Return方法。其实对象池的本质就是它的中的 ObjectWrapper[] _items ,当使用Return方法是,将对象放入ObjectWrapper数组中。Get方法从数组中取。

IPooledObjectPolicy:对象池策略接口

主要作用是创建对象和将对象放入连接池中。比如对象创建需要初始化操作,归还对象需要释放操作

Create:定义一个创建对象的方法,当连接池中的数量不够取的时候,通过此方法创建对象。
Return:将对象放入连接池中,如果放入成功,返回Ture.否则返回False.

PooledObjectPolicy

它是继承自IPooledObjectPolicy接口的抽象类

DefaultPooledObjectPolicy:默认的策略,继承抽象类PooledObjectPolicy

如果不需要定义复杂的构造逻辑,使用默认的就可以

Create:定义一个默认创建对象的方法 new T()
Return:不论是否放入连接池,全部返回True.

ObjectPoolProvider

抽象类,用于创建对象池(ObjectPool)

//通过Policy创建ObjectPool
abstract ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy)

DefaultObjectPoolProvider

ObjectPoolProvider的默认实现类

//创建一个可以容纳处理器数量X2的对象池
ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy) 

案例:

案例1、不指定创建策略,使用new T()

var objectPool = new DefaultObjectPoolProvider().Create<Person>();//or var objectPool = ObjectPool.Create<Person>();
Person p1 = objectPool.Get();//ID=0,Name=null

案例2、指定创建策略

var objectPool = new DefaultObjectPoolProvider().Create<Person>(new PersonPoolPolicy());
Person p1 = objectPool.Get();//ID=1,Name=fan

策略:

    public class PersonPoolPolicy : PooledObjectPolicy<Person>
    {
        public override Person Create()
        {
            return new Person { ID = 1, Name = "fan" };
        }

        public override bool Return(Person p)
        {
            if (p.Name != "fan")
            {//不允许其他名称的对象放入对象池
                return false;
            }
            return true;
        }
    }

案例3、在asp.net core中使用

先定义一个中间件

public class BirthdayMiddleware
{
    private readonly RequestDelegate _next;

    public BirthdayMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, ObjectPool<StringBuilder> builderPool)
    {
        var stringBuilder = builderPool.Get();
        try
        {
            stringBuilder.Append("Hi");
            // 其它处理
            await context.Response.WriteAsync(stringBuilder.ToString());
        }
        finally // 即使出错也要保证归还对象
        {
            builderPool.Return(stringBuilder);
        }
    }
}

在 Startup 中注册相应的服务和中间件:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();

        services.TryAddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
        {
            var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
            var policy = new StringBuilderPooledObjectPolicy();
            return provider.Create(policy);
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMiddleware<BirthdayMiddleware>();
    }
}

参考:
https://www.cnblogs.com/MicroHeart/p/11701647.html
https://mp.weixin.qq.com/s?__biz=MzAxMTA2MDYwNg==&mid=2650113279&idx=1&sn=2937fee06a5d806b87da036fd74ce870&chksm=8347f0eeb43079f80edff32ad83bf83e47737b26e161c4f5591cd80f051a27533ee703c8637d&mpshare=1&scene=23&srcid=0816j8rrzRAhLBAHjAWn5Axc&sharer_sharetime=1629114614691&sharer_shareid=e22c7e6a4276fb367680d85cb3e62f9d#rd
https://www.cnblogs.com/artech/p/object-pool-01.html#s1001

posted @ 2021-01-14 15:45  .Neterr  阅读(388)  评论(0编辑  收藏  举报