3

【C#/.NET】使用ASP.NET Core对象池 - 欲东

 9 months ago
source link: https://www.cnblogs.com/xuyd/p/17438313.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Nuget

Microsoft.Extensions.ObjectPool

使用对象池的好处

减少初始化/资源分配,提高性能。这一条与线程池同理,有些对象的初始化或资源分配耗时长,复用这些对象减少初始化和资源分配。比如:我有一个执行耗时约500毫秒,内存空间 2KB的任务为此创建一个新线程异步执行,而创建线程耗时1秒,内存空间占用1MB则得不偿失。

安装Nuget包:Install-Package Microsoft.Extensions.ObjectPool

builder.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();

使用对象池的第一步是实现IPooledObjectPolicy接口,要告诉对象池如何创建需要复用的对象

IPooledObjectPolicy接口有两个方法,

T Create()负责创建复用对象。

Return负责将复用的对象释放回对象池中。如果不调用Return,表示该对象在对象池被移除。

//对象池框架接口
public interface IPooledObjectPolicy<T> where T : notnull
{
    T Create();
    bool Return(T obj);
}

//我的复用对象的接口实现
public class ReuseObjectPolicy : IPooledObjectPolicy<ReuseObject>
{
    public ReuseObject Create()
    => new(DateTime.Now);

    public bool Return(ReuseObject obj)
    => true;
}
builder.Services.TryAddSingleton(serviceProvider =>
{
    var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
    var policy = new ReuseObjectPolicy();
    return provider.Create(policy);
});

对象使用通过依赖注入获取泛型ObjectPool对象的Get使用,关于泛型ObjectPool的定义如下

T Get()负责获取复用对象。

Return负责将复用的对象释放回对象池中。如果不调用Return,表示该对象在对象池被移除。

public abstract class ObjectPool<T> where T : class
{
    public abstract T Get();
    public abstract void Return(T obj);
}

获取ReuseObject复用对象,通过打印的创建事件和计数器可以知道,对象被复用了。而如果不调用Return,则会重新创建新的对象。

public class ReuseObject 
{
    private static  int _counter = 0;
    public ReuseObject(DateTime time)
    {
        Time = time;
        Interlocked.Increment(ref _counter);

        Console.WriteLine($"{Time}被创建了{_counter}次");
    }

    public DateTime Time { get; set; }
}

public class ObjectPoolController : ControllerBase
{
    private readonly ReuseObject _reuseObject;

    public ObjectPoolController(ObjectPool<ReuseObject> objectPool)
    {
        _reuseObject = objectPool.Get();
    }

    [HttpGet]
    public IActionResult Get()
    {
        var reuseObject = _objectPool.Get();
        try
        {
            Console.WriteLine($"创建时间是:{reuseObject.Time}");
        }
        finally
        {
            _objectPool.Return(reuseObject);
        }
        return Ok();
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK